-3
\$\begingroup\$

So I use this code, with a Rigidbody attached to my GameObject (player)..

using UnityEngine;

public class Player : MonoBehaviour
{
    public float speed = 4f;
    private float movement = 0f;
    public Rigidbody2D rb;

    private void Update()
    {
        movement = Input.GetAxisRaw("Horizontal") * speed;
    }

    void FixedUpdate ()
    {
        rb.MovePosition(rb.position 
            + new Vector2(movement * Time.fixedDeltaTime, 0f));
    }
}

The problem is the movement feels jerky / not smooth. It might just be me, though.

No, this is not a duplicate of a similar question. I am using other code and it's not totally similar to what I'm doing

\$\endgroup\$
6
  • \$\begingroup\$ Possible duplicate of Smoother object movement in Unity? \$\endgroup\$
    – Gnemlock
    Commented Dec 16, 2016 at 1:14
  • \$\begingroup\$ @Gnemlock No, It's different \$\endgroup\$
    – fnTASY
    Commented Dec 16, 2016 at 1:31
  • \$\begingroup\$ You should upload an animated gif of the result to stack's imgur so that we see what you mean. \$\endgroup\$
    – Vaillancourt
    Commented Dec 16, 2016 at 2:39
  • \$\begingroup\$ Can you define "feel"? \$\endgroup\$
    – Krythic
    Commented Dec 16, 2016 at 3:50
  • \$\begingroup\$ @fnTASY, if it is different, you need to explain how. All you ask for is "smooth movement", it is still very unclear what you actually mean (thus the downvote) \$\endgroup\$
    – Gnemlock
    Commented Dec 19, 2016 at 20:43

2 Answers 2

2
\$\begingroup\$

There are a few problems here. First, let's look at a typical series of frames in Unity:

  • Frame 1
    • Read Input
    • FixedUpdate
    • FixedUpdate
    • Update
    • Draw
  • Frame 2
    • Read Input
    • FixedUpdate
    • Update
    • Draw

So, the first thing to note is that you get different numbers of FixedUpdate calls from one frame to the next. This can create a visible judder, where the character appears to be moving at one speed, then you get a frame with fewer FixedUpdates and they appear to slow or stutter for a frame before continuing.

The simplest solution here is to enable Rigidbody Interpolation, and move the object using velocity. This will offset the rendered position of the object by whatever fractional timestep is needed to keep up with the frame time, without upsetting the predictable fixed timestep of the underlying simulation.

(Some folks don't like controlling characters via velocity, especially player characters, although I've generally found it quite workable. If it's not your style, you might prefer to remove the Rigidbody and move the object directly using its transform in Update, or use a character controller)

The second issue here is that you're capturing input in Update, but not actually using it until FixedUpdate. Since FixedUpdate runs before Update, that means you don't get to act on this information until the next frame, which adds latency to your game. For continuous values like Input.GetAxis, this data is already available and usable in FixedUpdate - so you can just grab it fresh when you want to use it. (Special care needs to be given to capturing instantaneous actions like Input.GetButtonDown though, to avoid missing or double-counting the events)

So, a fixed version might look like this - and it's simpler too! :)

public class Player : MonoBehaviour
{
    public float speed = 4f;
    public Rigidbody2D rb;

    void FixedUpdate ()
    {
        rb.velocity = Vector3.right * Input.GetAxis("Horizontal") * speed;
    }
}
\$\endgroup\$
0
\$\begingroup\$

You're using Input.GetAxisRaw, which returns the value with no smoothing filtering applied. This is useful ONLY if you want to do all smoothing of input processing by yourself.

In your case, just try to use Input.GetAxis instead.

\$\endgroup\$

You must log in to answer this question.

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