Fix physics jitter
Beginner Programmer
In Stride, there is no default smoothing applied to entities that are attached to physics entities. This can cause noticeable jitter, especially if the camera is attached to a character component.
In this tutorial, we will explore how to add smoothing to an entity using a SyncScript.
Note
You can also decrease the FixedTimeStep
in the physics settings configuration to achieve more accurate physics simulations. For example, changing it from 0.016667
to 0.008
will increase accuracy but at the cost of higher CPU usage.
Code to handle smoothing between two entities
The following code is all that's needed to smoothly attach two entities. Ensure that you unparent the entity you are trying to smooth, otherwise the transform processor will override this script.
[ComponentCategory("Utils")]
[DataContract("SmoothFollowAndRotate")]
public class SmoothFollowAndRotate : SyncScript
{
public Entity EntityToFollow { get; set; }
public float Speed { get; set; } = 1;
public override void Update()
{
var deltaTime = (float)Game.UpdateTime.Elapsed.TotalSeconds;
var currentPosition = Entity.Transform.Position;
var currentRotation = Entity.Transform.Rotation;
var lerpSpeed = 1f - MathF.Exp(-Speed * deltaTime);
EntityToFollow.Transform.GetWorldTransformation(out var otherPosition, out var otherRotation, out var _);
var newPosition = Vector3.Lerp(currentPosition, otherPosition, lerpSpeed);
Entity.Transform.Position = newPosition;
Quaternion.Slerp(ref currentRotation, ref otherRotation, lerpSpeed, out var newRotation);
Entity.Transform.Rotation = newRotation;
}
}
Example Usage
This example demonstrates modifications to the First Person Shooter template to integrate smooth camera movement.
- Detach the camera from the physics entity.
- Remove the FPS camera script from the camera.
- Create a new entity as a child of the character body.
- Add the FPS script to the new entity.
- Adjust any code that directly references the
CameraComponent
to reflect these changes.
PlayerInput.cs
Change
public CameraComponent Camera { get; set; }
to
public Entity Camera { get; set; }
Utils.cs
Change
CameraComponent camera
to
Entity camera,
and change
camera.Update();
var inverseView = Matrix.Invert(camera.ViewMatrix);
to
var inverseView = camera.Transform.WorldMatrix;
FpsCamera.cs
Remove
/// <summary>
/// Gets the camera component used to visualized the scene.
/// </summary>
private Entity Component;
and change
private void UpdateViewMatrix()
{
var camera = Component;
if (camera == null) return;
var rotation = Quaternion.RotationYawPitchRoll(Yaw, Pitch0);
Entity.Transform.Rotation = rotation;
}
to
private void UpdateViewMatrix()
{
var rotation = Quaternion.RotationYawPitchRoll(Yaw, Pitch, 0);
Entity.Transform.Rotation = rotation;
}
That should be all that is needed to see the smoothing in action as a before and after. You can see the original issue in the Stride GitHub here if you need to find more info on the problem.