Update() vs. FixedUpdate() for object rotation

I’m experiencing an issue where a game object appears to jitter while rotating at constant speed when the camera follows the object. This jitter is only present when updating the object’s rotation in FixedUpdate(); moving the rotation code to Update() eliminates the issue entirely.

Here are links to GIFs of the results: (The white rectangle in the GIFs helps make the jitter more pronounced)

Rotation code in FixedUpdate(), which looks incorrect: Imgur: The magic of the Internet

Rotation code in **Update()**, which looks correct: https://imgur.com/a/aAjthb3

Why is this jitter present? Unity convention is to put this code into FixedUpdate(), because it deals with physics calculations, so I’m seeking an understanding of why I am not able to perform this behavior in FixedUpdate(). Also in keeping with convention, the camera following code is in LateUpdate(), though changing this does not seem to have an effect.

I’ve tried too many different approaches to enumerate them, but I can’t resolve this issue without using Update(). I’m really interested to know why this doesn’t work as expected. Below I will attach the only two scripts in the project in their entirety. One is for the camera following behavior, and the other is for the character rotation.

PlayerRotation.cs

using UnityEngine;

public class PlayerRotation : MonoBehaviour {

	// Use this script by attaching it to a gameobject
	// that game object will rotate clockwise around the up axis

	public float spin_speed = 1.0f;

	void FixedUpdate () {

		Vector3 current_facing = this.transform.forward;
		Vector3 relative_target = this.transform.right;

		// pick a new direction to face that is some of the way to the right
		Vector3 new_facing = 
			Vector3.Lerp(
				current_facing,
				relative_target,
				spin_speed * Time.fixedDeltaTime
			);

		// set our direction to to the new facing
		this.transform.forward = new_facing;

	}
}

CameraFollower.cs

using UnityEngine;

public class CameraFollower : MonoBehaviour {

	// Use this script by attaching it to a gameobject with a camera
	// and supplying it with a target gameobject to follow

	public GameObject target;

	public float target_facing_smoothing_factor = 0.84f;

	private GameObject ghost_container;

	void Start () {

		// create a container to be centered on the target
		// make this camera a child of that container
		// rotating the container will maintain the camera's
		// relative offset and facing
		ghost_container = new GameObject(this.gameObject.name + " (container)");
		ghost_container.transform.parent = this.transform.parent;
		this.transform.parent = ghost_container.transform;
	}
	
	void LateUpdate () {

		// move the camera container to the target's location
		ghost_container.transform.position = target.transform.position;

		Vector3 current_facing = ghost_container.transform.forward;
		Vector3 target_facing = target.transform.forward;

		// rotate (some of the way) to the target's facing direction
		ghost_container.transform.forward =
			Vector3.Slerp(
				current_facing,
				target_facing,
				target_facing_smoothing_factor
			);

	}
}

Uhm… You don’t use physics in your rotation code actually.
To use physics you have to attach the Rigidbody component to the object and use either Rigidbody.AddTorque() or Rigidbody.MoveRotation().

Since you don’t use physics in your code, your code doesn’t work properly in FixedUpdate(). Update() and FixedUpdate() are fired in their own different times, Update() call time depends on the framerate while FixedUpdate() is framerate independent. You change the object rotation in FixedUpdate() every 0.04 seconds (default FixedUpdate tick time), and your Update() might be called 2-3 times between the FixedUpdate ticks, or there might be no Update() calls at all between 2 FixedUpdates. That’s why you have this jittering.

The answer to the original question, “why is there jittering when rotating using fixed update,” was indeed that the renderer was sometimes showing duplicate frames and sometimes not showing a frame for each state the object was in.

The first answer provided (as well as most answers I could find on the topic in researching the issue) stated that FixedUpdate() should be reserved for physics updates, or something similar. This is not correct, or at least rather misleading. Modifying the code above to use “physics” does not solve the jittering, nor does it address the underlying issue.

It is my determination that FixedUpdate() must be used for all calculations which impact the simulation or gameplay if either is to be deterministic and reproducible. The idea that FixedUpdate() is for physics is sort of correct in that, ideally, the physics should behave the same from run to run. The error is in stating that FixedUpdate() is for only physics. If it is necessary to make the simulation as close to deterministic as possible, all updates to the game’s state must occur in FixedUpdate(). In fact, that is what FixedUpdate() is for.

To put it simply, this is an understanding of the relationship between FixedUpdate() and Update() that is helpful to me:

FixedUpdate() is for calculations and updates involving the game world’s state, and is called at fixed intervals relative to game world time.

Update() is for any behavior which is not dependent on the game world’s time. This can be tricky to understand and get right, but the important take away is that anything that happens in Update() will appear to happen non-deterministically (“at random”) from the perspective of the game world. This makes it useful for collecting player input, but not for processing it, for example.

These are generalizations and elide all of the “why,” but I think this is a more accurate distinction than simply reserving FixedUpdate() for physics.

It should be noted that the code I originally provided already follows these conditions, but it has that unsightly jitter. There is a solution which enables the correct usage of FixedUpdate() (and therefore a deterministic simulation) and eliminates the jitter: build a state interpolator or extrapolator. In fact, doing so is necessary in order to both maintain reproducibility and show smooth motion of objects at a rate higher than the fixed time step of the game world.

Researching this issue proved to be difficult due to this conflation of purpose for FixedUpdate(). To really understand the issue, and to come up with a solution that worked for me, these sources were valuable:

A famous blog post explaining the implementation of a variable refresh rate game engine (which Unity is).

A Unity Forum discussion in which users debate the correct usage of Update(). The initial response is not correct, hence the length of the discussion.

A helpful visualization and Unity implementation of a possible solution to jitter.