Hello. I have a problem with camera and character shake. I change the player’s rotation via _rigidbody.MoveRotation(Quaternion.Slerp(_rigidbody.rotation, rotation, 0.15f));
This string is executed in Fixed Update. Cinemachine brain is configured for Smart update and Late update. If interpolate is enabled, the character twitches when rotating, but the camera looks good. If interpolate is disabled, the character stops twitching, but the camera starts twitching.
It’s because Rigidbody.MoveRotation is not compatible with interpolation when the RB is not kinematic. Unfortunately the Rigidbody docs are misleading and don’t make this clear.
Instead of using Rigidbody.MoveRotation, try using Rigidbody.angularVelocity. Maybe something like this:
#if false
// This code will break interpolation and cause jitter
var targetRotation = Quaternion.LookRotation(targetDir, Vector3.up);
rb.MoveRotation(targetRotation);
#else
// This code should be compatible with interpolation
var angle = Vector3.Angle(rb.rotation * Vector3.forward, targetDir) * Mathf.Deg2Rad / Time.fixedDeltaTime;
rb.angularVelocity = Vector3.up * angle;
#endif
Rigidbody.MoveRotation is perfectly compatible with Interpolation if the rigidbody is kinematic. However, Rigidbody.MoveRotation causes issues in non-kinematic rigidbodies because it overrides the results of the physics solver.
In non-kinematic rigidbodies, the physics engine computes the velocities as a result of the current state and conditions. These velocities will be used in interpolation. However, Rigidbody.MoveRotation modifies the Rigidbody to a state different than the expected initially, hence the jittering.
If wanting to rotate a dynamic rigidbody with MoveRotation then you should do it from Update. This is especially useful for player controllers where you may prefer fast response times. Rotating a rigidbody using rb.angularVelocity or rb.AddTorque from FixedUpdate will be smooth but less responsive.
Interacting with RBs in Update does nothing. It just stores/accumulates the arguments until the next FixedUpdate takes place, and then the RB is updated in the physics world. So the response time not only will be the same, but also adds potential glitches and inconsistencies depending on the frame rate the application runs at.
If you want fast response times with rigidbodies:
Always interact with RBs from FixedUpdate.
Increase the physics update rate by modifying Project Settings > Time > Fixed Timestep.
The default is timestep 0.02 (50 Hz). Set it to 0.01 to get 100 Hz, which duplicates the response time. Or even 0.005 for 200 Hz, and so on (frequency = 1 / timestep).
The rigidbody is updated in FixedUpdate but it’s interpolated in Update. I’m not an expert on the inner workings of PhysX but it may be that the interpolator will update the interpolated position between FixedUpdates when using MoveRotation or MovePosition from Update. But theory aside - in practice it’s definitely more responsive.
Increasing the physics update rate can be okay but it’s not going to get you the same responsiveness of Update unless you set the FixedUpdate rate to match Update, which will then lead to the physics behaving differently on different monitors.
BTW - I’m well aware there’s other ways to get a more responsive camera…