Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / game / Unity

Day 63 of 100 Days of VR: Rotating a Vector and Moving in the Direction the Player Is Facing In Unity

5.00/5 (1 vote)
27 May 2018CPOL4 min read 1.8K  
How to rotate a Vector and move in the direction the player is facing in Unity

Introduction

In the previous post, we just added some simple code that allows our character to move with the touchpad. Easy stuff, nothing too complicated.

Now there’s one problem that we might discover depending on how we want movement to work in the game.

We can move forward just fine, but what happens when we try to move our character after we turn around?

We still end up moving in the same direction regardless of where we started at!

There are some assumptions of how the player plays in our game. The player could be:

  • Sitting down so that we are always facing the same direction
  • Standing up so they can turn around in a full 360-degree angle and moving forward is wherever they’re looking at

Our solution works for the first scenario, but for the second scenario, it doesn’t work.

After battling this problem for a long time, the solution I came to solve this problem is that we’re going to have to use good old math and vector multiplication! We’re going to learn how to rotate vectors!

The main problem is that when we update our position, we’re updating it based off the parent game object that’s holding the camera and not based off of where we are looking at (the main camera). And we can’t just get rid of the parent container, because we need it to hold our camera.

What we must do is rotate the vector we calculated earlier based off where the player is looking at.

Adding Movement Based Off of Player Direction

This took a lot of time to solve, but here’s the updated code for our TouchpadMovement script:

C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TouchpadMovement : MonoBehaviour
{
    private float _speedSlowDown;
    private Camera _mainCamera;

    void Start()
    {
        _speedSlowDown = 0.1f;
        _mainCamera = Camera.main;
    }

    void Update()
    {
        if (GvrControllerInput.IsTouching)
        {
            Vector2 touchPos = GvrControllerInput.TouchPos;
            Vector3 movementVector = new Vector3(touchPos.x - 0.5f, 0, 
                    touchPos.y - 0.5f);                 //adjust for center to be at 0.5, 0.5
            Vector3 rotatedVector = 
                       RotateVector(movementVector, _mainCamera.transform.eulerAngles.y);
            transform.Translate(rotatedVector.x * _speedSlowDown, 0, 
                    -rotatedVector.z * _speedSlowDown); // negative to adjust for the vector speed   
        }
    }

    // Given a direction and a degree, 
    // we'll rotate the direction vector by the given degree amount
    private Vector3 RotateVector(Vector3 direction, float degree)
    {
        float radian = Mathf.Deg2Rad * degree;          // convert our degree to be in radians

        // calculate our rotation vector using matrix multiplication
        // source: https://en.wikipedia.org/wiki/Rotation_matrix
        float cos = Mathf.Cos(radian);
        float sin = Mathf.Sin(radian);
        float newX = direction.x * cos - direction.z * sin;
        float newZ = direction.x * sin + direction.z * cos;
        return new Vector3(newX, 0, newZ);
    }
}

Walking Through the code

You would not believe all the work that it took me to derive this!

There were a lot of attempts to try and get this correct. The first thing I tried to do use was Quaternion.AngleAxis() to calculate the rotation Quaternion to rotate our vector. However, that did not get the correct values after playing around with it for a LONG time.

With the Unity APIs not working for me, I decided that I had no other choice, but to use trigonometry to figure out how we would rotate a vector. The result of that is in RotateVector().

Understanding RotateVector()

The problem that we’re trying to solve is that the vector we get to move around is based off us going forwards, but if we want to go in the direction that the player is facing, the vector we create from the touchpad is no longer correct.

What we must do is rotate our vector so that “forward” is the forward direction of our Main Camera.

The information we have right now is:

  • The angle our main camera is facing
  • The player input movement vector

Armed with this information and my high school diploma, I had no clue what I was supposed to do!

I know that I had to do something with Sin(X) and Cos(X) and that was as much as my memory would help me!

Luckily, we have the internet! Specifically, Youtube! This video on rotating a vector, talks about how we would calculate the new X and Y value of a rotated vector, it was very informative.

Wikipedia also had a very nice page on rotation matrix for rotating our vector.

However, the TLDR is this:

X’ = X * Cos(radian) – Y * Sin(radian)

Y’ = X * Sin(radian) – Y * Cos(radian)

It’s important to note that it’s important to convert our angle to radian, looking at the documentation of Mathf.Cos() and Mathf.Sin():

“Returns the cosine of angle f in radians.”

I made the mistake of thinking that we would pass in angle and they would give us a value in radians…. No… I was horribly mistaken. The function means give an angle that’s converted to radian form.

How did I confirm this? Anyone remember Unit Circles?

That’s right, I plugged these values into Unity and I found out that we had to convert our degree into radians.

Cue flashbacks of High school math class where your teacher always tells you to make sure you’re in degree mode. I’ve failed you teach!

Anyways. Go ahead and try playing around with the script on the Unity emulator. Look around and try to slide your touchpad by pressing: Shift + Ctrl + Mouse Movement. No matter what way you’re facing, we’ll now be able to move in the correct location.

And with that accomplished, we can move on to other ways to interact with the game controllers!

Conclusion

Phew, that was more math than I originally thought would be needed for movement!

If you ever wondered if you needed math for programming, this is an example of when you do (Hint: not often).

Now, we can move our character by using the touchpad, but not only that, if we were to turn ourselves around in the game and move, we’ll move in the direction that we’re looking at.

With this finished, we’re officially done with locomotion. Next up, we’re going to look at how to pick up and throw objects with our controller and how to use our motion to be able to throw it! See you guys in the next post!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)