Reverse direction of gameObject on collision
I'm having problems reversing the direction of my gameObjects once one of them hits a collider (around the game screen). I've tried looking at the solutions to similar questions but cannot for the life of me get this to work!
I have box colliders around my screen (tagged "Collider") as well as circle colliders around my gameObjects. None of the colliders have 'is trigger' ticked. My gameObjects also have a Kinematic RigidBody2D component on them (as I am making a puzzle-type game and my gameObjects don't move in the easier levels). For each puzzle, I generate a random value (on a separate script), and this value determines the initial movement of my gameObjects (there are 5 objects in different positions but move in the same direction).
At the moment, my gameObjects move in a random direction but do not reverse directions once they hit the collider. I'm trying to get all of the gameObjects to keep reversing directions once one of them hits a collider on the edge of the screen (so that if the objects are moving up and hits the collider, they all move down then back up again once they hit the bottom collider, and so forth). I've attached my current code below. This script is attached to all of my gameObjects. If someone could help me understand where I'm going wrong and how to fix this, it would be greatly appreciated!
public class RocketStimuli : MonoBehaviour
{
public Vector2 currentDirection = new Vector2();
private void Update()
{
if (level.currentLevel == 6)
{
RocketMovement();
}
}
private void RocketMovement()
{
//left movement
if (level.randomDirection == 1)
{
currentDirection = Vector2.left;
transform.Translate(currentDirection * level.moveSpeed * Time.deltaTime, Space.World);
}
//right movement
else if (level.randomDirection == 2)
{
currentDirection = Vector2.right;
transform.Translate(currentDirection * level.moveSpeed * Time.deltaTime, Space.World);
}
//up movement
else if (level.randomDirection == 3)
{
currentDirection = Vector2.up;
transform.Translate(currentDirection * level.moveSpeed * Time.deltaTime, Space.World);
}
//down movement
else if (level.randomDirection == 4)
{
currentDirection = Vector2.down;
transform.Translate(currentDirection * level.moveSpeed * Time.deltaTime, Space.World);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Collider"))
{
currentDirection = -currentDirection;
}
}
}
change
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Collider"))
{
currentDirection = -currentDirection;
}
}
to
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Collider"))
{
switch (level.randomDirection) {
case 1:
level.randomDirection = 2;
break;
case 2:
level.randomDirection = 1;
break;
case 3:
level.randomDirection = 4;
break;
case 4:
level.randomDirection = 3;
break;
}
}
}
or some of its mathematical variant. the point is to switch the direction in level. not the currentDirection vector (because that one is being set every frame depending on the level.randomDirection)
Answer by Dartictheunic · Jul 31, 2019 at 09:34 AM
You're changing currentDirection, which is calculated during RocketMovement(). What you're wanting to do is to change level.randomDirection.
Something along the lines of
int newDirection()
{
int newDir = Random.Range(1,3);
if(newDir == level.randomDirection)
{
newDir ++;
return newDir;
}
else
{
return newDir;
}
}
And then in OnCollisionEnter2D you can put
level.randomDirection = newDirection();
NOTE: This implies you can change level.randomDirection, else you might want to create a new float and set it to + or - 1 and then multiply currentDirection by it, I can't tell more with what you wrote.
Sidenote: you might want to create a new void to change currentDirection to avoid assigning it a value during Update(), but that's purely from an optimization point of view.
Thanks for your reply. I've tried to multiply currentDirection by a new float (newDirection = -1) as you've suggested but it still didn't work. I also added a Debug.Log("hit") in the OnCollisionEnter2d method but nothing gets printed out onto the console either. I've attached screenshots of the colliders and gameObjects if this will give more information. Thanks in advance for your help!
public class RocketStimuli : $$anonymous$$onoBehaviour
{
public Vector2 currentDirection = new Vector2();
private int newDirection = -1;
private void Update()
{
if (level.currentLevel == 6)
{
Rocket$$anonymous$$ovement();
}
}
private void Rocket$$anonymous$$ovement()
{
//left movement
if (level.randomDirection == 1)
{
currentDirection = Vector2.left;
transform.Translate(currentDirection * level.moveSpeed * Time.deltaTime, Space.World);
}
//right movement
else if (level.randomDirection == 2)
{
currentDirection = Vector2.right;
transform.Translate(currentDirection * level.moveSpeed * Time.deltaTime, Space.World);
}
//up movement
else if (level.randomDirection == 3)
{
currentDirection = Vector2.up;
transform.Translate(currentDirection * level.moveSpeed * Time.deltaTime, Space.World);
}
//down movement
else if (level.randomDirection == 4)
{
currentDirection = Vector2.down;
transform.Translate(currentDirection * level.moveSpeed * Time.deltaTime, Space.World);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Collider"))
{
currentDirection *= newDirection;
Debug.Log("hit");
}
}
}
I've also got the following line in a method that gets called when a new puzzle is presented:
randomDirection = Random.Range(1, 5);
alt text
In Unity: your objects must have Rigidbodies in order to fire OnCollisionEnter (both the rocket and the walls)
Codewise: Once again you're setting currentDirection during Rocket$$anonymous$$ovement() so your changes are overwritten almost instantly.
But you could create a bool reverse (for exemple) that you set to true inOnCollisionEnter2D() and change your Rocket$$anonymous$$ovement() as follows:
private void Rocket$$anonymous$$ovement()
{
//left movement
if (level.randomDirection == 1)
{
currentDirection = Vector2.left;
}
//right movement
else if (level.randomDirection == 2)
{
currentDirection = Vector2.right;
}
//up movement
else if (level.randomDirection == 3)
{
currentDirection = Vector2.up;
}
//down movement
else if (level.randomDirection == 4)
{
currentDirection = Vector2.down;
}
if(reverse == true)
{
currentDirection *=-1f; //multiplying by -1 will invert the Vector
}
transform.Translate(currentDirection * level.moveSpeed * Time.deltaTime, Space.World); //we put translate at the end so the movement is done after checking if it must be inverted
}