Need help keeping camera in place (counter players rotation)

Hey guys,

I’m currently working on a networking implementation of a character controller which allows the player to keep the camera in place when holding the left mouse button, like in WoW, Aion or other MMORPG’s.

I usually get the player inputs & set the transform rotation inside Update(), while doing all the camera stuff in LateUpdate().

Now the networking engine of the project requires me to set the transform’s rotation inside FixedUpdate(), which results in stuttering of the camera when countering the player’s rotation.

Any idea how I could fix that issue?

Please see the problem in action here: Dropbox

Just hold the left mouse button and press W or A.

Can you elaborate on why you need to update the camera in FixedUpdate? The local camera isn’t really something that gets passed around the network.

The players entity is rotated inside fixedupdate, not the camera, and I want to counter that rotation inside lateupdate.

Here is the script from the demo:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class test : MonoBehaviour {

    private float rotationSpeed = 200f;
    private Vector3 pivot = new Vector3(0.25f, 1.25f, 0);

    public Camera mainCam;

    private float yaw;
    private float counter;

    private void Update () {
        yaw += Input.GetAxis("Horizontal") * rotationSpeed * Time.deltaTime;
        yaw %= 360f;
    }

    private void FixedUpdate () {
        transform.rotation = Quaternion.Euler(0, yaw, 0);
    }

    private void LateUpdate () {
        if (Input.GetMouseButton(0))
            counter -= Input.GetAxis("Horizontal") * rotationSpeed * Time.deltaTime;

        Vector3 offset = -transform.forward;
        offset.y = 0.0f;
        offset *= 5f;

        Quaternion x = Quaternion.AngleAxis(0, transform.right);
        Quaternion y = Quaternion.AngleAxis(counter, Vector3.up);
        Quaternion rotation = y * x;

        Vector3 camPivot = transform.position + transform.TransformVector(pivot);

        mainCam.transform.position = camPivot + rotation * offset;

        mainCam.transform.LookAt(camPivot);
    }
}

Have you tried lerping the Camera position towards its destination transform values?

yes, doesn’t seem to help much.

Rather than “countering the rotation”, why don’t you try storing the current camera’s rotation on mouse down and statically set to that rotation as long as the mouse continues to be held down?

I thought about that too, but in my final script I also use the counter variable to include moving the cam with the mouse.

But I’m also interested to fix this issue without the workaround you mentioned, as I had a similar problem with fixedupdate in the past.

There will often be stuttering even when relying only on Update() which is called once per frame (see Wolfram’s top answer here for a detailed description why). The problem of stuttering can well be exacerbated by the mix of Update() and FixedUpdate() again as referenced by Wolfram’s same answer.

Maybe you could double lerp - one in Update() and one in FixedUpdate() to try and harmonise, as best you can, the considered ‘current position’ across the two different timing methods?