Maintain constant speed after rotation

Hello if I have the following simple code:

    public float speed = 1;

    void Update()
    {
        Vector3 displacement = transform.forward * speed;
        
        transform.position += displacement;
    }

I know that, if I don’t rotate the game object the script is attached to, the game object move forward
at a speed of 1 meter/sec. So displacement will be 0,0,1 and transform.position, starting at 0,0,0 will
be 0,0,1 then 0,0,2 etc. So my game object is moving along z at that speed.

If I rotate the object, say at 66 degree on y, then I’ll have transform.forward with 0.9135, 0, 0.4067 so displacement will be 0.9135, 0, 0.4067 and at the end transform.position will be 0.9135, 0, 1.4067 then 0.9135, 0, 1.8135 etc meaning that on z is moving at 0.4067 meter/sec.

So when I rotate the object my speed decrease.

How can I always move object at the same speed (i.e, 1 meter/sec) if I rotate it?

This should be in the scripting forum.

Have you tested it?

Your z transform would not go to 1.4067, because the displacement is not 0,0,1. The displacement is 0.9135,0,0.4067. The position will go 0,0,0, then 0.9135,0,0.4067, then 1.827,0,0.8134 (if my math is right).

Do you want to move your object in the direction it is facing (regardless of whether or not that is the z axis), or do you want to move your object in the direction of the z axis?

1 Like

Just a note. Anything done in Update that you want to be constant, you have to multiply by Time.deltaTime.

Vector3 displacement = transform.forward * speed * Time.deltaTime;

Update is executed every frame, but it is executed after different time spans. DeltaTime is expressed in seconds, so if your speed is meters per second, it will work better.

In FixedUpdate you need to multiply by Time.FixedDeltaTime (don’t use Time.DeltaTime even though it says in the documentation to use the first one because it returns a different value in case you are in FixedUpdate… It’s not clear and a bad design idea).

1 Like

Which is correct, because you’re moving it at 1m/sec along its own “forwards” direction, not along the world z axis.

If you want to move along the world z axis then you shouldn’t be using transform.forward, you should just be using Vector3.forward, or “new Vector3(0, 0, 1)”.

Another issue is that you’re not taking the time step into account, as @Darkgaze says. This will make your speed inconsistent because you’ll be moving the same distance each update regardless of how long that update took.

Edit: Corrected an error, for the sake of future readers.

1 Like

Yes, starting from 0,0,0 your math is right. I had taken as my starting point 0,0,1. However the results does not change.
Then I want to move the object in the direction it is facing that is its forward direction on z axis.

Oh, yes I know that. I omitted it just to simplify the calculations. Thx

Based on what I understood transform.position and transform.forward are related to world position not local position.So when I rotate my object the local direction on z is always on 0,0,1 but the world direction is changed to the values based on 66 degree. So I want to move the object in the direction it is facing (its forward z) but taking into account rotation and always at 1 m/sec. I can’t use Vector3.forward because it not take into account the rotation.

Sorry, my use of the word “local” there was incorrect. I meant its “own” forward direction. You are correct that this is represented in world space.

Then what you’re already doing is correct, as long as you account for the time delta.

I’m a bit confused, because you said this:

The speed has not decreased, the issue is that you’re only looking at one component of the object’s position. If you also consider the X and Y components you’ll see that the total moved distance is in fact 1 unit.

Can you please describe what’s actually happening when you move your object around? Eg: when is it the wrong speed?

Also, you said that the code you showed here is simplified. Can you please show the code you’re actually using? Perhaps the issue is elsewhere.

You already are.

Remember that the object’s forward z is NOT the same as the world’s forward z. If you want to understand this, just consider that you’re moving from polar to cartesian coordinates when you start using things like rotation and an object’s “forward z.”

x = r * cos(phi)
y = r * sin(phi)

1 * cos(0) = 1 * 1 = 1
1 * sin(0) = 1 * 0 = 1

1 * cos(66) = 1 * 0.4067 = 0.4067
1 * sin(66) = 1 * 0.9135 = 0.9135

This is normal behavior.

What about this behavior do you not like? Do you want it to be in the same position afterwards in both scenarios, just facing different directions? If you can describe the behavior you want, we can probably tell you how to get it.

Thank you for your patience. I miscalculated. This is what happens.
In the scene I have a cube at the initial position 0.0.0 and a rotation of 0.0.0.
I start the demo, pause and do 3 steps:

  • Cube, position 0.0.1, rotation 0.0.0.
  • Cube, position 0.0.2, rotation 0.0.0
  • Cube, position 0.0.3, rotation 0.0.0

In accordance with the Pythagorean theorem I find the magnitudine of the vector displacement = |(0, 0, 1) | = 1

I rotate the cube 66 degrees around the Y-axis and take 2 more steps;

  • Cube, position 0.9135455, 0, 3.406737, rotation 0, 66, 0
  • Cube, position 1.827091, 0, 3.813473, rotation 0, 66, 0

According to the Pythagorean theorem I find the magnitude of the vector displacement = | (0.9135455, 0, 0.406737) | = 1

So, displacement is always 1 and so even with one rotation I always maintain the same speed.

Thanks again!

1 Like

Big thumbs up for doing the math by hand to check the results!