Should I be using time.fixedDeltaTime here?

I’m very new and working on a simple fps movement script based on various tutorials I’ve found. I find my movement is not as completely smooth as I would like it to be. I am wondering if this:

    private void Run()
    {
        vel.z = vInput * speed;
        vel.x = hInput * speed;
    }
    private void FixedUpdate()
    {
        Run();
        Jump();
        rb.velocity = transform.TransformDirection(vel);
    }

should be using Time.fixedDeltaTime when setting the vel vector’s x and z to the key input.

Should I be using deltaTime somewhere here, should I be using SmoothDamp, or Lerp? I don’t yet understand exactly where and how I should be applying these tools for the smooth, consistent movement I want. I’ll paste the entire (fairly short) script below in case anyone has any pointers for me. Thanks.

using UnityEngine;

public class PlayerMovement_1P : MonoBehaviour
{
    private Rigidbody rb;
    private Vector3 vel;
    private float vInput, hInput, jumpInput;
    public float speed, jumpVel, distToGround, downAccel;
    public LayerMask ground;

    private void Start()
    {
        if (GetComponent<Rigidbody>())
            rb = GetComponent<Rigidbody>();
        else
            Debug.LogError("The character needs a rigidbody.");

        vInput = hInput = jumpInput = 0;
        vel = Vector3.zero;
    }

    private void GetInput()
    {
        vInput = Input.GetAxis("Vertical");
        hInput = Input.GetAxis("Horizontal");
        jumpInput = Input.GetAxisRaw("Jump");
    }

    private void Run()
    {
        vel.z = vInput * speed;
        vel.x = hInput * speed;
    }

    private void Jump()
    {
        if (jumpInput > 0 && IsGrounded())
        {
            vel.y = jumpVel;
        }
        else if (jumpInput == 0 && IsGrounded())
        {
            // Zero out y vel when on ground and not jumping
            vel.y = 0;
        }
        else
        {
            // Not grounded - falling
            vel.y -= downAccel;
        }
    }

    bool IsGrounded()
    {
        return Physics.Raycast(transform.position, Vector3.down, distToGround, ground);
    }

    private void Update()
    {
        GetInput();
    }

    private void FixedUpdate()
    {
        Run();
        Jump();
        rb.velocity = transform.TransformDirection(vel);
    }
}

Edit: When writing this answer, I overlooked the fact that you are setting a rigidbody velocity. A velocity is already “distance / time”, so multiplying with Time.deltaTime would divide by time again, leaving you with “distance / time²”, which is an acceleration, not a velocity. So, in your case, the Rigidbody internally uses Time.deltaTime already when applying its velocity, thus you shouldn’t use it. Thanks @senilo for pointing that out.

Original answer:

FixedUpdate does not get called with constant timesteps - that is impossible on modern computers. But it does act like it is - by getting called more or less often in order to have the correct number of calls on average. This allows FixedUpdate code to assume a constant call rate even though there is none, so you don’t have to multiply with Time.deltaTime (which, by the way, during FixedUpdate has the same constant value as Time.fixedDeltaTime).

The game will run in a deterministic way using FixedUpdate - and multiplying the (then-)constant factor of Time.deltaTime will not change that in any way.

However, the value still functions as a “per second”.
If you move by one meter every FixedUpdate, with the default fixed timestep of 0.02, you move 50 meters per second. So putting your speed factor to 1 means 50 m/s, which seems quite arbitrary. If you want a speed of exactly 6 m/s, you might already want to whoop out the calculator. Even worse: If you change your project’s fixed timestep at some point, your scripts will change their behaviour. Top speeds will have to be fixed on all objects.

So, multiplying Time.deltaTime in FixedUpdate does serve a purpose: It changes the semantics of the values you set in your script’s properties from “per fixedupdate” to “per second” and makes your scripts more robust to changes in the project’s fixed timestep. Thus, I recommend using it.

Unsure, and there’ll hopefully be a better answer on its way, but have you tried setting the rigidbody’s Collision Detection field to ‘continuous’? It will be more expensive but it will give better physics calculations; not something you want for most things, but for the player.

Also I notice you are using input to determine whether to add velocity within the fixed update; be warned that input is only updated immediately after the Update() method, and persist until the end of the next Update(). So if for example you pressed Jump and 3 fixed updates occurred before the next update, your fixedupdates will have that same jump input for those 3 updates. You’re checking if the player is on the ground so you shouldn’t notice the extra jump inputs (and by default there’s only about 1 fixed update per update anyway), but I thought I’d mention it. One fix would be to set a bool in Update() that says whether to jump or not, then clear that bool as soon as it’s resolved in fixedupdate so future fixedupdates that frame aren’t affected.

If you want smooth movement you should use Rigidbody.AddForce(). It’s like that:

[SerializeField]private float speed;
private Rigidbody rbody;

private float inputH, inputV;

void Start ()
{
    rbody = GetComponent<Rigidbody>();
}

void FixedUpdate ()
{

    inputH = Input.GetAxis("Horizontal");
    inputV = Input.GetAxis("Vertical");

    float moveX = inputH * speed * Time.fixedDeltaTime;
    float moveZ = inputV * speed * Time.fixedDeltaTime;

    rbody.velocity = new Vector3(0, rbody.velocity.y,0);

    rbody.AddForce(transform.Forward * moveZ * Time.fixedDeltaTime, ForceMode.Force);
    rbody.AddForce(transform.Right * moveX * Time.fixedDeltaTime, ForceMode.Force);

}

Hope I’ve helped.

Try to apply the velocity directly in Update(), I don’t see any reason why you have to do it in FixedUpdate()

The default timestep for FixedUpdate() is 50 Hz, so if your game is running at 60 fps, you don’t apply the controls on every frame.

Try this:

    private void Update()
    {
        GetInput();
        Run();
        Jump();
        rb.velocity = transform.TransformDirection(vel);
    }

Edit: and decrease the physics time step

Try do like this :

 private void FixedUpdate()
 {   
     IsGrounded();
 {
 private void Update()
 {
     Input();
     Run();
     Jump();
     rb.velocity = transform.TransformDirection(vel);
 }
  • You can see this life cycle in here : Unity - Manual: Order of execution for event functions

  • As you can see in the life cycle, the FixedUpdate called multiple times in one cycle, why the reason i put IsGrounded() in the FixedUpdate() is maybe when my character in the ground it not called and throug the object that should called true value.

  • That is just example for it, but when it’s not needed(not troubling/ make a bug like i said before) you can put it in Update() after move or before input, it can gaining more FPS cause it just called one time.

[Edited]

  • Use Time.deltaTime that called in Update() and Use Time.fixedDeltaTime that called in FixedUpdate().

[Edited]

Hope it helps.