How to make an object go the direction it is facing?

I have a cube that is my player and I can move it with WASD. I can also rotate it with QE. When I rotate it though, it still goes the the same direction when I press a directional button. It doesn’t matter what direction it is facing. So how can I make it always go forward based on the front of the cube? Any help would be much appreciated.

Script:

using UnityEngine;
using System.Collections;

[RequireComponent (typeof(Rigidbody))]
public class Movement : MonoBehaviour {

	public float movementSpeed = 5.0f;
	public float clockwise = 1000.0f;
	public float counterClockwise = -5.0f;

	void Start () {
		
	}
	
	void Update () {
		if(Input.GetKey(KeyCode.W)) {
			transform.position += Vector3.forward * Time.deltaTime * movementSpeed;
		}
		else if(Input.GetKey(KeyCode.S)) {
			rigidbody.position += Vector3.back * Time.deltaTime * movementSpeed;
		}
		else if(Input.GetKey(KeyCode.A)) {
			rigidbody.position += Vector3.left * Time.deltaTime * movementSpeed;
		}
		else if(Input.GetKey(KeyCode.D)) {
			rigidbody.position += Vector3.right * Time.deltaTime * movementSpeed;
		}

		if(Input.GetKey(KeyCode.E)) {
			transform.Rotate(0, Time.deltaTime * clockwise, 0);
		}
		else if(Input.GetKey(KeyCode.Q)) {
			transform.Rotate(0, Time.deltaTime * counterClockwise, 0);
		}
	}
}
1 Like

Vector3.forward and the others are in world space, so they will always move you in the same direction no matter which direction your character is in. To fix this you can replace the Vector3.forward with transform.forward. transform.forward is the forward direction of the transform, taking rotation into account.

So you change this:

transform.position += Vector3.forward * Time.deltaTime * movementSpeed;

Into this:

transform.position += transform.forward * Time.deltaTime * movementSpeed;

Transform does not have the variables left and back though, so you use the negative version of right and forward instead. Or simply subtract movement instead of adding it.

Move Back:

transform.position -= transform.forward * Time.deltaTime * movementSpeed;

Use AddRelativeForce - which adds a force to the rigidbody relative to its / local coordinate system, rather than AddForce which adds based on the world’s coordinate system.


code solution / sample



E.g: If the spaceship is rotated away from the station, pressing forward with AddRelativeForce will use the ship’s position and rotation, moving the ship forward in the correct direction. AddForce will use the station’s / world’s coordinates and ignore the ship’s rotation - so when you press forward, the ship will move backward, towards the station.

If you’re movement is physics based you can calculate the angular velocity…
I use this in movement of some robot characters and needed more than just a simple Lerp.
Here’s a typical rigidbody movement motor… Assuming you have 2 vectors, point a the position of the game object, b the position of the target to move to…

// First calculate the force - ...
...
Vector3 nextDirection = (b - a).normalized;                       
Vector3 targetVelocity = nextDirection * speed;
Vector3 deltaVelocity = targetVelocity - thisRigidbody.velocity;
                                 if (thisRigidbody.useGravity)
                                        deltaVelocity.y = 0;

 force = deltaVelocity * accelerationRate;
// Then we can calculate the angular velocity

                // Make the character rotate towards the target rotation
                var turnDir = nextDirection;
                if (turnDir == Vector3.zero) 
                {
                        angularVelocity = Vector3.zero;
                }
                else 
                {
                        var rotationAngle = AngleAroundAxis (transform.forward, turnDir, Vector3.up);
                        angularVelocity = (Vector3.up * rotationAngle * turningSmoothing);
                }

Then you can set the rigidbody –

thisRigidbody.AddForce (force, ForceMode.Acceleration);
thisRigidbody.angularVelocity = angularVelocity;

Here is how to calculate the angle around an axis (make it turn around its head y axis)

public static float AngleAroundAxis (Vector3 dirA, Vector3 dirB, Vector3 axis) 
                {
                    // Project A and B onto the plane orthogonal target axis
                    dirA = dirA - Vector3.Project (dirA, axis);
                    dirB = dirB - Vector3.Project (dirB, axis);

                    // Find (positive) angle between A and B
                    float angle = Vector3.Angle (dirA, dirB);

                        // Return angle multiplied with 1 or -1
                    return angle * (Vector3.Dot (axis, Vector3.Cross (dirA, dirB)) < 0 ? -1 : 1);
                }

To make sure it doesn’t overshoot make use of a in range calculation and the adjust the speed for the component above. You can do this with ( b - a).magnitude or Vector3.Distance. The trick is to calculate the gradual deceleration or you can just make it stop with a speed = 0. Let me know if you need more help.

Change position to Translate, you just helped me solve the opposite problem.

transform.Translate(Vector3.forwardspeedtime.dealtatime);

I would certainly advise against setting (adding in this case) the position every time you move the player.
Please either use transform.Translate() as the replies above suggest, or go all the way and add a rigidbody and use GetComponent().AddForce(Vector3.forward * Time.deltaTime * movementSpeed) in order to also give unity the power to also calculate collisions (if you have a collider attached) and physics if necessary.