6
\$\begingroup\$

I have a new project, all settings default with a simple cube on a plane. Cube is not kinematic but is a rigid body under the effects of gravity. I'm trying to normalize the direction before I translate it to prevent diagonal movement from being too fast. The movement is perfectly smooth when I just translate by the speed, but when I try to normalize it and multiply that vector, the movement becomes jittery and feels delayed, almost. I have no idea what the cause could be. Here's the code in question. It takes place in the Update() override:

    float directionHorizontal = Input.GetAxis("Horizontal");
    float directionVertical = Input.GetAxis("Vertical");

    Vector3 translationDirection = new Vector3(directionHorizontal, 0, directionVertical);
    translationDirection.Normalize();

    translationDirection *= Speed * Time.deltaTime;
    transform.Translate(translationDirection);

EDIT: After some further tinkering and testing, I'm finding that the problem is more specifically that the movement seems to jump from frame to frame rather than move smoothly from one spot to another. It seems like it's moving the right speed, but this kind of really fast start/stop gives it that jerky feel.

Is this normal behavior? Shouldn't the delta time multiplication smooth out the movement and give it a more interpolated feel? This happens even if i avoid the normalization method and just multiply the axis by speed and time.

\$\endgroup\$
4
  • \$\begingroup\$ Are you sure it's the Normalize() that's causing the jitter? You can easily verify by commenting just that one statement out. \$\endgroup\$ Sep 11, 2013 at 5:15
  • \$\begingroup\$ I just tested the same code on a different computer and it's not jittering at all, so it could have been an issue on the machine I was running. I'll investigate it further and close this if that's the case. \$\endgroup\$
    – ssb
    Sep 11, 2013 at 5:21
  • \$\begingroup\$ Which script callback are you running your code in? Update or FixedUpdate? \$\endgroup\$ Sep 11, 2013 at 20:00
  • \$\begingroup\$ This is in update \$\endgroup\$
    – ssb
    Sep 12, 2013 at 23:53

3 Answers 3

3
\$\begingroup\$

When you start moving, input values returned by Input.GetAxis() normally (with default Input settings) don't jump instantly from 0 to 1 but rather are gradually increased during several frames, even if you use digital input (such as keyboard keys) rather than a gamepad's analog stick.

Now, the problem is that after normalization, your direction vector has magnitude = 1.0 even if movement speed supposed to be small, which gives this sudden jump from speed = 0 to speed = 1 as soon as you start moving:

Vector3 translationDirection = new Vector3(0.1f, 0, 0);  // slowly moving to the right
translationDirection.Normalize();  // results in Vector(1, 0, 0)

Rather than normalizing this vector, you should instead limit its magnitude only when necessary:

Vector3 translationDirection = new Vector3(directionHorizontal, 0, directionVertical);
translationDirection = Vector3.ClampMagnitude(translationDirection, 1);

This will give you smooth increase in speed when you start moving (or decrease when stopping), while at the same time preventing from exceeding the maximum speed.

\$\endgroup\$
2
\$\begingroup\$

Don't have enough rep to comment yet so I'll take a stab at an answer.

I had a similar problem in an XNA project I was working on a few months ago. The issue I was having was caused by scaling the object. Basically the physics wasn't being scaled by the same amount as everything else and that resulted in jitter.

You don't seem to be building up a force either. Was that the intention? Apologies if any of this is incorrect / irrelevant I'm attempting to answer before my early morning coffee.

\$\endgroup\$
2
\$\begingroup\$

Try placing this code in FixedUpdate() instead of Update().

Physics motions happen in FixedUpdate() and Update() is synched with draw calls. The two don't always happen at the same frequency. Most of the time this is the cause of the jittery motion.

So, if you are going to affect the motion of a physically-simulated object, you need to do it in FixedUpdate().

Now, why does it happen only when you do the normalization? Probably it's because the extra processing time required by Normalize() causes the Update calls to lag more behind FixedUpdate. The fact that it acts differently in different computers also supports this idea. How much out-of-sync Update and FixedUpdate get depends a lot on the available CPU cycles, which tends to be nondeterministic.

\$\endgroup\$

You must log in to answer this question.

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