I have got a little problem with my cinemachine follow - stuttering.
I think it is similar problem as described here:
He said that it is working correctly in build but I would it to be working correctly in editor mode.
This is a script I’m using to copy my Entity position and rotation to my cinemachine target GameObject.
public class CopyEntityPositionComponent : MonoBehaviour
{
private void Update()
{
var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
var playerControlledQuery =
entityManager.CreateEntityQuery(ComponentType.ReadOnly<IsPlayerControlledTag>());
using var playerControlledEntities = playerControlledQuery.ToEntityArray(Allocator.Temp);
if (playerControlledEntities.Length <= 0)
{
return;
}
var localTransform = entityManager.GetComponentData<LocalTransform>(playerControlledEntities[0]);
transform.SetPositionAndRotation(localTransform.Position, localTransform.Rotation);
}
}
Note that the order of code execution with ECS looks like this:
ECS → InitializationSystemGroup
MonoBehaviour → Update
ECS → SimulationSystemGroup
MonoBehaviour → LateUpdate
ECS → PresentationSystemGroup
As you can see, if you’re reading entity positions in a MonoBehaviour Update function, you’re getting values calculated in the previous frame.
As a workaround, you can switch to LateUpdate.
I usually prefer to put my code into systems instead, since it gives me more explicit control over when it runs, and lets me get rid of the World.DefaultGameObjectInjectionWorld.EntityManager.CreateEntityQuery etc stuff.
So I have switched everything to Late Update. My script is now working in LateUpdate and my Cinemachine brain Update method is working in Lateupdate.
I still have this jerky movement.
Also why should it matter when I set the position. Let’s just say that I have got values of the position of previous frame, it still should not be jerky but just lagging one frame.
Is the entity moved by physics? If so, LocalTransform is just the simulation position, not the interpolated one that is used for rendering/presentation. If you want those you need to follow/copy LocalToWorld.
This is a symptom that the target is moving unevenly. Recall that Update and LateUpdate are called every render frame, and render frames do not happen at even intervals. If your ECS system which moves the underlying entity is running on even timesteps (in the same manner as FixedUpdate), then you’re likely to see fixed-frame aliasing: some render frames will include more fixed frames than others. This will result in jerky movement.
With Physx, the Interpolation feature takes care of this by copying to the transform at render time an appropriate value calculated to account for the uneven timestep. Maybe you should do something similar.
Note that your reference video is very old. ECS has evolved since then.
Thank you guys, I was able to solve the issue, your comments pushed me in the right directions.
Actually I’m using custom interpolation since I’m not using physics. I’m running my game logic in fixed update (might be different than physics).
Are you sure it is LocalTransform and not RigidTransform when it comes to Physics ?
And LocalTransform is actually the interpolated position.
I’m doing it like this right now, I’m storing my position and rotation in components, and than I’m interpolating it in different system, interpolated result ends up in LocalTransform.
The problem was with the interpolation, but I have to say that this system is very sensitive. I’m guessing you are calculating velocity internally every frame, so a spike of velocity change not visible by human eye may end up messing the camera behaviour.
Right now I’m interpolating my LocalTransforms in SimulationSystemGroup.
And I’m copying the result in LateUpdate to cinemachine target(GameObject)