# Using Unity's transform.translate() to translate relative to an object but only using two axis

I'm using transform.translate() to move an object around the world space, relative to the camera that is following it. The camera has an angle of 23 degrees on the X axis.

The problem is that when I move forward the object tries to go into the ground and when going backward the object starts jumping because of the angle of the camera. What I want to do is freeze the Y axis of the object However if I did this the object would no longer be able to jump.

The other solution to this would be to write a method which rests the object to the ground when not jumping but them if the object was jumping and going backwards it would go flying backwards again.

How do I solve this issue?

• The behaviour of the camera you described is a little hard to understand. Can you post the script which controls the object? It would greatly clarify what you are trying to achieve. – The Light Spark Nov 14 '15 at 15:22
• The camera is static, with X rotation set to 23. The object simply moves using transform.Translate(speed * Time.deltaTime * Input.GetAxis("Horizontal"), 0, Time.deltaTime * Input.GetAxis("Horizontal") * speed, camera.transform); – user3797758 Nov 14 '15 at 16:09
• Remove the camera.transform argument from the function call. Is then what you get is the correct way the object should move? Do you want the camera to always look at the object, wherever it goes? – The Light Spark Nov 14 '15 at 16:42
• no because then the object moves it it's local space were as i need it move in relation to the camera. The camera will always look at the object but it will look at it in different ways depending on how the camera/object moved before getting into the current position. The answer bellow worked for me in the end :) – user3797758 Nov 14 '15 at 20:15

Figured it out. Essentially i'm taking the position of the object before and after then taking the difference of both of then then adding it back into the position, so that the difference in Y-axis position that is introduced from the camera transform.Translate() is compensated for.

//compensate for the rotation of the camera while moving
void CompensateTransform(float X, float Y)
{
float diffrence = transform.position.y;
transform.Translate(speed * Time.deltaTime * X, 0,
Time.deltaTime * Y * speed, camera.transform);
diffrence -= transform.position.y;
transform.position = new Vector3(transform.position.x,
transform.position.y + diffrence,
transform.position.z);
}

• Note that this corrects for the vertical error, but not the forward error. Since part of your forward movement went into raising/lowering the object, the remaining movement along the correct forward axis will be slightly less than the expected speed amount. The result is the player will move faster when going straight left/right than when going straight forward/back (where they'll go cos(23 degrees) ~ 92% of the intended speed). The usual fix is to use your camera vectors to construct a local coordinate frame aligned with the floor, and move using that. I can show you how if you like. – DMGregory Nov 15 '15 at 15:12
• Yes but i can correct for that with the speed that i set the object to move at. The accuracy of the speed isn't that important just the direction of movement. – user3797758 Nov 16 '15 at 16:30
• So, just to confirm: you're not interested in a solution that fixes this problem? – DMGregory Nov 16 '15 at 16:33
• huh apparently the comment i made yesterday didn't show up.... Anyway if you want to post it post it i'm sure someone who comes across this post will find it useful – user3797758 Nov 18 '15 at 16:50

Here's a method that won't foreshorten your forward & backward movement:

Quaternion GetGroundFrame()
{
// You can replace this with a raycast if you have more complex levels,
// to get the direction of the collision plane under the character.
Vector3 groundNormal = Vector3.up;

transform cam = Camera.main.transform;

// Construct a rotation that points your nose away from the ground,
// and your chin roughly toward the camera's forward direction.
Quaternion frame = Quaternion.LookRotation(groundNormal, -cam.forward);

// Note that this will need a little special handling if your camera
// can ever look nearly straight up/down along the ground normal.

// Rotate the coordinate frame 90 degrees forward.
frame = frame * Quaternion.AngleAxis(90f, Vector3.right);

return frame;
}


Then you can do something like:

Quaternion frame = GetGroundFrame();
Vector3 offset = new Vector3(r, 0, f) * speed * Time.deltaTIme;

// Multiplying by frame transforms the movement-space offset
// into worldspace.
transform.translate(frame * offset, Space.World);


you should simply use transform.position += vector3.forward * speed * time.deltatime;

make a variable of type float for speed like below: private float speed = 2f;

also use vector3.back or vector3.right and so on... for other directions

• How would you adapt the the yaw of the game camera using this method? – DMGregory Jan 3 at 9:57