Marcus79
Marcus79

Reputation: 87

How can I check if an object is facing a certain direction in Unity C#

Still pretty new to Unity and C#. I can usually find my way around when it comes to setting/changing the position of an object, but when it comes to rotation it's still mind boggling to me, with quaternion, eulerangles etc..

I'm trying to check if an object (a head) is facing a certain direction, if it's not facing that direction it needs to set it to that direction depending which way it goes (up, down, left or right). This is for a snake game (like the old top down nokia game) I'm currently developing.

I tried to look it up, but none of the answers are specific to what I'm trying to do.

As of right now this is what I have for player input (a snippet of code):

private int GetAxisRaw(Axis axis)
    {
        if (axis == Axis.Horizontal)
        {
            bool left = Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.A);
            bool right = Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.D);

            if (left)
            {
                snakeHeadRotation.transform.Rotate(0, 180, 0); // Keeps rotating when left is pressed
                return -1;
            }
            if (right)
            {
                snakeHeadRotation.transform.Rotate(0, -180, 0);
                return 1;
            }

            return 0;
        }

As you can see the snakeHeadRotation.transform.Rotate(0, 180, 0); is getting called each time the player presses the left key for instance, thus turning the head of the snake even when the snake is still traveling to the left.

My logic would be to store the rotation value somewhere (type Quaternion/bool maybe) and check to see if that rotation value matches up with the current rotation value set to left (which is snakeHeadRotation.transform.Rotate(0, 180, 0);) If that's the case, don't do anything. If it isn't, set it to snakeHeadRotation.transform.Rotate(0, 180, 0); for instance.

the code would look something like (writing it out):

private int GetAxisRaw(Axis axis)
{
    if (axis == Axis.Horizontal)
    {
        bool left = Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.A);
        bool right = Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.D);

        if (left && rotation is not equal to snakeHeadRotation.transform.Rotate(0, 180, 0))
        {
            snakeHeadRotation.transform.Rotate(0, 180, 0); 
            return -1;
        }
        if (right)
        {
            snakeHeadRotation.transform.Rotate(0, -180, 0);
            return 1;
        }

        return 0;
    }

As said, I'm very unfamiliar with setting or storing rotation values. How can I achieve this? Is this even the right approach or is there a more logical one? I can't figure this one out myself..

I hope I explained it right, I'm usually terrible at explaining things.

Upvotes: 3

Views: 7667

Answers (3)

Cristian Bontas
Cristian Bontas

Reputation: 77

You could compare the current rotation to the known rotations for the 4 directions. But don't go that way, it's bad practice for several reasons:

  • what if later you want to add animations, e.g. the head turns in .5 seconds, not instantly?
  • comparing 4 floats only to check one of 4 possible directions is inefficient.

Create a enum instead:

public enum Direction
{
    Up,
    Down,
    Left,
    Right
}

Add a member of this type to your behavior, to keep track of where your snake head is going. Something like:

    Direction direction;
...
private int GetAxisRaw(Axis axis)
{
    switch (direction)
    {
        case Direction.Up:
            if (left && !right)
               direction = Direction.Left;
               ... turn snake left ...
            else if (right && !left)
               direction = Direction.Right;
               ... turn snake right ...
            // ignore inputs for up or down if going up
        break;
        ... repeat for the other directions and possible inputs ...
    }
    ...
}

Upvotes: 1

Ben Pyton
Ben Pyton

Reputation: 338

Using Transform.Rotate(x) will rotate your head by x degrees relatively to your current head direction.

What you want I suppose is to set the absolute rotation of your head depending on the arrow key you pressed. Thus, even if you press multiple times the same arrow key, the head will stay in the correct direction.

To do that you can create 4 rotations for each head direction and so use them as needed. For example, if your head is facing forward by default:

// create your directions
private static Quaternion forwardDirection = Quaternion.Identity;
private static Quaternion rightDirection = Quaternion.FromToRotation(Vector3.forward, Vector3.right);
private static Quaternion leftDirection = Quaternion.FromToRotation(Vector3.forward, Vector3.left);
private static Quaternion backDirection = Quaternion.FromToRotation(Vector3.forward, Vector3.back);

...

private int GetAxisRaw(Axis axis)
{
    ...

    if (left)
    {
        // set the absolute direction of your head to the left
        snakeHeadRotation.transform.rotation = leftDirection; 
        return -1;
    }
    if (right)
    {
        // set the absolute direction of your head to the right
        snakeHeadRotation.transform.rotation = rightDirection;
        return 1;
    }

    ...
}

Upvotes: 2

Tom Sebty
Tom Sebty

Reputation: 302

I would just create 4 quaternions for each direction and set the rotation according to the key pressed (so like hear.rotation = leftQ). This is the simplest way.

I am away from my PC currently but I will try to find another solution when I can

Upvotes: 1

Related Questions