Mike H
Mike H

Reputation: 407

Unity get mouselook to be smooth and framerate independent

I've been confusing myself about Update() vs FixedUpdate() and time.deltaTime vs time.fixedDeltaTime for this situation.

I want frame-rate independent movement for the camera mouse-look but at the same time I want it to be as smooth as possible for 60 fps. For some reason, 60 fps seems slightly jittery.

My question is, do I put the function below inside of Update() or FixedUpdate()? Should the deltaTime variable be time.deltaTime or time.fixedDeltaTime to achieve this? Or am I doing this all wrong?

Thanks for any input.

BTW the SmoothDamp function below is a smoothing function based on lerp that allows for the feedback

void MouseLook()
{
    if (_isEscaped)
        return;

    if (!_isAllowedToLook)
        return;

    var deltaTime = Time.fixedDeltaTime;

    var adjustedSensitivity = _lookSensitivity * 100f; //Keeps sensitivity between 0.1 and 10f but makes the sensitivity in math actually work

    _lookInput.x = SmoothDamp.Float(_lookInput.x, Input.GetAxis("Mouse X"), _lookSmoothSpeed, deltaTime);
    _lookInput.y = SmoothDamp.Float(_lookInput.y, Input.GetAxis("Mouse Y"), _lookSmoothSpeed, deltaTime);

    // Mouse look
    var newVerticalPitch = _verticalPitch + _lookInput.y * -adjustedSensitivity * deltaTime;
    _verticalPitch = SmoothDamp.Float(_verticalPitch, newVerticalPitch, 15f, deltaTime);
    _verticalPitch = Mathf.Clamp(_verticalPitch, -_maxVerticalLookAngle, _maxVerticalLookAngle);             //Clamp vertical look

    // Camera vertical rotation
    var newCameraRotation = Quaternion.Euler(Vector3.right * _verticalPitch);
    _camTransform.localRotation =
        SmoothDamp.Quaternion(_camTransform.localRotation, newCameraRotation, 15f, deltaTime);


    // Player horizontal rotation
    var newPlayerRotation = _transform.rotation * Quaternion.Euler(_lookInput.x * adjustedSensitivity * deltaTime * Vector3.up);
    _transform.rotation = SmoothDamp.Quaternion(_transform.rotation, newPlayerRotation, 15f, deltaTime); //Player rotation
}

Upvotes: 0

Views: 4170

Answers (1)

Darren Ruane
Darren Ruane

Reputation: 2485

Update and FixedUpdate are both callback functions that Unity invokes on your Monobehaviours at certain times during their lifetime. More specifically, Update is called every frame (assuming the Monobehaviour is enabled) and FixedUpdate is called every physics frame.

Physics frames are independent of graphical frame-rate and are set from within Unity to occur at a specific interval. The default is 50 times per second (in other words FixedUpdate runs at 50fps by default).

FixedUpdate is generally a function that you should reserve for your physics-based needs (such as using RigidBodies or ray-casting etc.) and most certainly not one to use for things such as getting user input.

Now that that is hopefully cleared up, let's address Time.deltaTime and Time.fixedDeltaTime:

Time.fixedDeltaTime returns the amount of time that has passed since the previous FixedUpdate() frame ran. Now, since we know from above that FixedUpdate() runs at a constant frame-rate (50 by default) this value will more or less always be the same between frames

Time.deltaTime similarly returns the amount of time that has passed since the previous Update() frame ran. Now, since Update() does not run at a constant frame-rate, but is dependent on the user's machine, this value is almost always going to be a little different each frame.

So with all of this in mind, should this go in Update() or FixedUpdate()? And should it use Time.deltaTime or Time.fixedDeltaTime?

If I've done a decent job at explaining the differences between these things, then I would expect you to now know that it ought to go in Update() and use Time.deltaTime.

I do not know what that SmoothDamp.Float() method is doing exactly, but by lerping between two positions using Time.deltaTime as the t parameter, you will ensure that no matter what the frame-rate of the machine running this is, that it will be smooth and consistent.

Upvotes: 2

Related Questions