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?

  • \$\begingroup\$ 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. \$\endgroup\$ Commented Nov 14, 2015 at 15:22
  • \$\begingroup\$ 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); \$\endgroup\$ Commented Nov 14, 2015 at 16:09
  • \$\begingroup\$ 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? \$\endgroup\$ Commented Nov 14, 2015 at 16:42
  • \$\begingroup\$ 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 :) \$\endgroup\$ Commented Nov 14, 2015 at 20:15

3 Answers 3


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, 
  • \$\begingroup\$ 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. \$\endgroup\$
    – DMGregory
    Commented Nov 15, 2015 at 15:12
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Nov 16, 2015 at 16:30
  • \$\begingroup\$ So, just to confirm: you're not interested in a solution that fixes this problem? \$\endgroup\$
    – DMGregory
    Commented Nov 16, 2015 at 16:33
  • \$\begingroup\$ 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 \$\endgroup\$ Commented Nov 18, 2015 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;

(See more on the derivation of this coordinate frame here)

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

  • 1
    \$\begingroup\$ How would you adapt the the yaw of the game camera using this method? \$\endgroup\$
    – DMGregory
    Commented Jan 3, 2019 at 9:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .