Is there a way to make a character move relative to the main camera? As in if I press left, the character moves to the cameras left, then if the camera orbits around them to a new position the character still moves to the cameras left when the same button is pressed.
You can get the camera’s current left vector with Camera.main.transform.left. Then apply that vector to your character via your favorite way to move the character.
var cameraLeftVector = Camera.main.transform.left;
character.transform.Translate(cameraLeftVector, Space.World);
If you don’t want to rotate the object then its pretty straightforward:
Vector3 dir;
dir = Camera.main.transform.forward; // forward
// dir = -Camera.main.transform.forward; // back
// dir = Camera.main.transform.right; // right;
// dir = Camera.main.transsform.left; // left;
dir.y = transform.position.y
dir.Normalize();
transform.Translate(dir * speed * Time.deltaTime);
The commented out directions what you need to set based on direction your going (use a switch).
This code:
- Sets our forward vector to be the same as the camera’s
- Then we set our up portion of the foward vector to be the up of our character. We do this because if the camera is titled down (or up) we will walk down into the ground, or up in to the sky. We want just walk walk on the XZ plane the character is already in. If there is no “ground” and you need the object to move in free space the way the camera is exactly pointing comment this line out
- Normalize is just so walking left/right/up/down is the same as walking diagonal if your code does that. if you want diagonal walking to be faster comment that out.
This is exactly what i need.
But would there be a way to combine two of the directions, like forward and right or left and back for diagonal movement?
This is the code i use to rotate the character based on WASD input, and i think this is where i could use your code.
(Also, for some reason Camera.main.transform.left and .back aren’t showing up in auto select)
public void RotateTowardsMoveDirection()
{
if (MoveVector.x != 0 || MoveVector.z != 0)
{
if (MoveVector.z > 0)
{
if (MoveVector.x > 0)
Rotation = Quaternion.Euler (0, Camera.main.transform.rotation.eulerAngles.y + 45, 0);
else if (MoveVector.x < 0)
Rotation = Quaternion.Euler (0, Camera.main.transform.rotation.eulerAngles.y + 305, 0);
else
Rotation = Quaternion.Euler (0, Camera.main.transform.rotation.eulerAngles.y, 0);
}
else if (MoveVector.z < 0)
{
if (MoveVector.x > 0)
Rotation = Quaternion.Euler (0, Camera.main.transform.rotation.eulerAngles.y + 135, 0);
else if (MoveVector.x < 0)
Rotation = Quaternion.Euler (0, Camera.main.transform.rotation.eulerAngles.y + 225, 0);
else
Rotation = Quaternion.Euler (0, Camera.main.transform.rotation.eulerAngles.y + 180, 0);
}
else
{
if (MoveVector.x > 0)
Rotation = Quaternion.Euler (0, Camera.main.transform.rotation.eulerAngles.y + 90, 0);
else if (MoveVector.x < 0)
Rotation = Quaternion.Euler (0, Camera.main.transform.rotation.eulerAngles.y + 270, 0);
else
Rotation = transform.rotation;
}
}
transform.rotation = Quaternion.Lerp (transform.rotation, Rotation, 0.25f);
}
yes. they are just vectors. So just add them together like this:
dir = Camera.main.tranform.forward + Camera.main.tranform.left;
However, .forward and .left are unit vectors. but when you add them together you get the proper direction, but its length is going to be >1. That is why I have the dir.Normalize() call to rescale this new vector back to unit length. Unless, like I said in the original post, you want walking diagonal to be faster, then don’t normalize it.
That works and gives me the correct movement i need. Thanks a lot : D
Unfortunately,
dir.y = transform.position.y,
doesn’t stop the character from moving towards the ground or sky. Or rather, when the cameras is looking at them from above or below they move very slowly.
Also, now the character continues to move just a bit even after the WASD keys are released, and now moves more suddenly than smoothly.
Any idea why that is?
try:
dir = new Vector3(dir.x, transform.position.y, dir.z);
Unfortunately my version
MoveVector = new Vector3 (MoveVector.x, transform.position.y, MoveVector.z);
doesn’t seem to work.
I use it after line 36 in post #4, then Normalize it.
transform.rotation = Quaternion.Lerp (transform.rotation, Rotation, 0.25f);
MoveVector = new Vector3 (MoveVector.x, transform.position.y, MoveVector.z);
if (MoveVector.magnitude > 1)
MoveVector = Vector3.Normalize (MoveVector);
what is the Rotation being set to? If that is rotating your character so he faces up or down… then transform.position.y will still move him up or down.
Rotation is just being used to rotate the character around its y axis, to make it face left, right, forward or back and any of the diagonal combinations.
Rotation, based on WASD input and any of its combinations (forward, back, forward-right, back-left) is given a number like 45 for 45 degrees (forward-right). This number is added to the cameras euler y axis. Its then used to rotate the character, so no matter where the camera is around the player they’ll always rotate to face which direction their heading in, relative to the camera.
That’s all RotateTowardMoveDirection() in post #4 is doing, with the if, else if and else statements, seeing which combination is pressed and assigning the appropriate amount to turn the character.
Try to add some Debug.Log lines and record them just before he moves off in the wrong direction:
Useful variables to see are:
Camera.main.rotation, transform.rotation, Rotation, and moveVector
Also catch them before you normalize. Would be easier to math things out
That is stick all 4 Debug Logs right before you check the magnitude of the moveVector. You might be able to figure out whats wrong from the numbers, or if not post them here
This is transform.rotation and MoveVector while the character is moving, right before the normalizing.
transform.rotation should be the the Quaternion, the one with four values.
Hope i got it right for you.
Ok i’ll look at these… though I might suggest in the future instead of just
Debug.Log(moveVector) to try Debug.Log("MoveVector: " + moveVector);
Would make a long list of different number much more decipherable.
Actually I don’t know enough about the internals of Unity Quaternions. I should have been much more explicit for all the rotations soemthing like this:
Debug.Log("transform rotation: " + transform.rotation.eulerAngles.
Then i can visualize and do the math on those xyz rotation angles to see whats going on.
Okay…
Here’s:
else if (MoveVector.x < 0)
{
Debug.Log(Rotation = Quaternion.Euler (0, Camera.main.transform.rotation.eulerAngles.y + 270, 0));
Debug.Log(MoveVector = -Camera.main.transform.right);
}
else
Rotation = transform.rotation;
}
}
Debug.Log(transform.rotation = Quaternion.Lerp (transform.rotation, Rotation, 0.25f));
Debug.Log(MoveVector = new Vector3 (MoveVector.x, transform.position.y, MoveVector.z));
if (MoveVector.magnitude > 1)
MoveVector = Vector3.Normalize (MoveVector);
}
with the character moving left and the camera looking down at them, causing the slow movement.
I’m not use to using Debug so sorry if this method is erroneous.
Closer. But still all the Debugs are showing the Quaternions in the internal format. I would need to see the actual x,y,z angles like this:
else if (MoveVector.x < 0)
{
Rotation = Quaternion.Euler (0, Camera.main.transform.rotation.eulerAngles.y + 270, 0);
Debug.Log("Rotation: " + Rotation.eulerAngles);
MoveVector = -Camera.main.transform.right;
Debug.Log("MoveVector : " + MoveVector);
}
else
Rotation = transform.rotation;
}
}
Debug.Log("Camera Rotation: " + Camera.main.rotation.eulerAngles);
Debug.Log("Transform Before Lerp: " + transform.rotation.eulerAngles);
transform.rotation = Quaternion.Lerp (transform.rotation, Rotation, 0.25f);
Debug.Log("Transform After Lerp: " + transform.roation.eulerAngles);
MoveVector = new Vector3 (MoveVector.x, transform.position.y, MoveVector.z);
if (MoveVector.magnitude > 1)
MoveVector = Vector3.Normalize (MoveVector);
}
For some reason the Rotation and MoveVector debugs weren’t showing up in this one.

There also didn’t seem to be a debug about strafing left. Which i think is the only way to get thsoe 2 debugs. I guess you just weren’t strafing left.
Though that particular set of data just shows your character not rotation at all, so either he got rotated downward some other time, or the MoveVector is pointing downward. Whats the MoveVector right before its normalized?
The camera is definitely tilted downward,its spun 80 degrees forward around the world X axis.
God i’m such a bonehead.
Yeah, moving left made the other two show up.
Thanks for being patient with my inexperience.
I noticed that when moving to the left the character doesn’t slow down when the camera is looking down at them, but are when moving forward are back like you said before.



