Time.DeltaTime in ComponentSystems wrong? Smooth follow camera

I have a camera follow system, which worked very smoothly until a few versions ago.
I had it manually updating in a FixedUpdate call.
However I think with Entites 0.30 or 0.40 it stopped working smoothly and now is very choppy. It doesn’t matter if I let it auto-run or manually fix-update it (in fact FixedUpdate is even worse, it is choppy all the time, the auto-update is somewhat smooth but seems to lag behind every 1-2 seconds or so and then jumps a little)

How can I get a smooth follow camera with DOTS right now?

public class CameraFollowSystem : ComponentSystem
{
    private EntityQuery query;
    private float smoothing = 20f;
    private float3 offset = new float3(0, 2, -7);

    protected override void OnCreate()
    {
        query = GetEntityQuery(
            ComponentType.ReadOnly<LocalToWorld>(),
            ComponentType.ReadOnly<PlayerShipComponent>());
    }

    protected override void OnUpdate()
    {
        var localToWorlds = query.ToComponentDataArray<LocalToWorld>(Unity.Collections.Allocator.TempJob);

        if (localToWorlds.Length > 0)
        {
            var dt = Time.DeltaTime;

            Entities.WithAllReadOnly<CameraComponent>().ForEach((ref Translation camPosition, ref Rotation camRotation) =>
            {
                var ltw = localToWorlds[0];
                var trans = ltw.Position;
                var rot = ltw.Rotation;

                var targetPos = trans + (math.mul(rot, offset));
                camPosition.Value = math.lerp(camPosition.Value, targetPos, smoothing * dt);

                var lookTo = math.normalize((trans + ltw.Forward * 100f) - camPosition.Value);
                var toRot = quaternion.LookRotation(lookTo, ltw.Up);
                camRotation.Value = math.slerp(camRotation.Value, toRot, smoothing * dt);
            });
        }
        localToWorlds.Dispose();
    }
}

I convert the camera with ConvertAndInject, and manually add a CopyTransformToGameObject

public class CameraAuthoring : MonoBehaviour, IConvertGameObjectToEntity
{
    public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    {
        dstManager.AddComponentData(entity, new Unity.Transforms.CopyTransformToGameObject());
    }
}

Did some more testing. My systems that are supposed to update in FixedUpdate give wildly different Time.deltaTime values when they are updated.
I Debug.Log the deltaTime in the FixedUpdate and then in the OnUpdate Methods of my systems, and get these results:


I guess this the cause for the jerkiness of my camerasystem.
What is the solution to this?

My FixedUpdate System

using Unity.Entities;
using UnityEngine;

public class RunFixedUpdateSystems : MonoBehaviour
{
    //private InputSystem playerInputSystem;
    //private PlayerTurningSystem playerTurningSystem;
    //private PlayerAnimationSystem playerAnimationSystem;

    private CameraFollowSystem cameraFollowSystem;
    private MovementSystem movementSystem;

    private void Start()
    {
        //    playerInputSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<InputSystem>();
        //    //playerTurningSystem = World.Active.GetOrCreateSystem<PlayerTurningSystem>();
        //    //playerAnimationSystem = World.Active.GetOrCreateSystem<PlayerAnimationSystem>();

        cameraFollowSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<CameraFollowSystem>();
        movementSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<MovementSystem>();

    }

    private void FixedUpdate()
    {
        //playerInputSystem.Update();
        //playerMovementSystem.Update();
        //playerTurningSystem.Update();
        //playerAnimationSystem.Update();

        if (cameraFollowSystem == null) cameraFollowSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<CameraFollowSystem>();
        if (movementSystem == null) movementSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<MovementSystem>();

        cameraFollowSystem.Update();
        movementSystem.Update();

        Debug.Log("RunFixedUpdateSystems deltaTime: " + Time.deltaTime + " fixedDeltaTime: " + Time.fixedDeltaTime);
    }
}

My camera system

using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
using UnityEngine;

[DisableAutoCreation]
public class CameraFollowSystem : ComponentSystem
{
    private EntityQuery query;
    private float smoothing = 20f;
    private float3 offset = new float3(0, 2, -7);

    protected override void OnCreate()
    {
        query = GetEntityQuery(
            ComponentType.ReadOnly<LocalToWorld>(),
            ComponentType.ReadOnly<PlayerShipComponent>());
    }

    protected override void OnUpdate()
    {
        var localToWorlds = query.ToComponentDataArray<LocalToWorld>(Unity.Collections.Allocator.TempJob);

        if (localToWorlds.Length > 0)
        {
            var dt = Time.DeltaTime;

            Entities.WithAllReadOnly<CameraComponent>().ForEach((ref Translation camPosition, ref Rotation camRotation) =>
            {
                var ltw = localToWorlds[0];
                var trans = ltw.Position;
                var rot = ltw.Rotation;

                var targetPos = trans + (math.mul(rot, offset));
                camPosition.Value = math.lerp(camPosition.Value, targetPos, smoothing * dt);

                var lookTo = math.normalize((trans + ltw.Forward * 100f) - camPosition.Value);
                var toRot = quaternion.LookRotation(lookTo, ltw.Up);
                camRotation.Value = math.slerp(camRotation.Value, toRot, smoothing * dt);
            });
            Debug.Log("Camera: " + dt);

        }
        localToWorlds.Dispose();

    }
}

My movement system:

using Unity.Entities;
using Unity.Jobs;
using Unity.Transforms;
using Unity.Physics;
using Unity.Mathematics;
using UnityEngine;

////[UpdateInGroup(typeof(SimulationSystemGroup))]
//[DisableAutoCreation]
//public class MovementSystem : JobComponentSystem
//{
//    protected override JobHandle OnUpdate(JobHandle inputDependencies)
//    {
//        var dt = Time.DeltaTime;

//        return Entities.ForEach((ref PhysicsVelocity velocity, in LocalToWorld ltw, in MovementInfo movementInfo) =>
//        {
//            //velocity.Linear = math.lerp(velocity.Linear, movementInfo.Thrust * 50 * ltw.Forward, 0.5f * dt);//movementInfo.Thrust * 50 * dt * ltw.Forward;
//            velocity.Linear = movementInfo.Thrust * 50 * dt * ltw.Forward;
//            velocity.Angular = math.lerp(velocity.Angular, movementInfo.Input * 0.8f, 30f * dt);
//        }).Schedule(inputDependencies);

//    }
//}

[DisableAutoCreation]
public class MovementSystem : ComponentSystem
{
    protected override void OnUpdate()
    {
        var dt = Time.DeltaTime;

        Entities.ForEach((ref PhysicsVelocity velocity, ref LocalToWorld ltw, ref MovementInfo movementInfo) =>
        {
            //velocity.Linear = math.lerp(velocity.Linear, movementInfo.Thrust * 50 * ltw.Forward, 0.5f * dt);//movementInfo.Thrust * 50 * dt * ltw.Forward;
            velocity.Linear = movementInfo.Thrust * 50 * dt * ltw.Forward;
            velocity.Angular = math.lerp(velocity.Angular, movementInfo.Input * 0.8f, 30f * dt);
        });
        Debug.Log("Movement: " + dt);
    }
}

5565544--574003--upload_2020-3-8_23-44-44.png

As you’re updating in FixedUpdate you should use fixedDeltaTime instead of DeltaTime. That should help.

There does not seem to be a fixedDeltaTime in ComponentSystems.

Did some more testing, this definitly seems strange:
5569621--574606--upload_2020-3-9_22-4-11.png

I am logging Time.deltaTime, Time.fixedDeltaTime, Time.time and the differences in Time.time and System.DateTime.Now.Milliseconds since the last FixedUpdate() call in my system runner.

I am also logging Time.DeltaTime, Time.ElapsedTime and the differences in Time.ElapsedTime and System.DateTime.Now.Milliseconds since the last OnUpdate() call in my camera system.

I suspect System.DateTime.Now.Milliseconds is not very precise, but all those values seem to be off.

Interesting enough, the Time.DeltaTime syncs with the calculated difference of Time.ElapsedTime in the camera system when the difference is around 0.010.
This can be seen in the second to last log entry marked by the arrow.

Most of the time Time.DeltaTime is around 0.010 and the calculated difference is around 0.020 (as expected by the Time.fixedDeltaTime value of 0.02)

The system runner

using Unity.Entities;
using UnityEngine;

public class RunFixedUpdateSystems : MonoBehaviour
{
    //private InputSystem playerInputSystem;
    //private PlayerTurningSystem playerTurningSystem;
    //private PlayerAnimationSystem playerAnimationSystem;

    private CameraFollowSystem cameraFollowSystem;
    private MovementSystem movementSystem;

    private void Start()
    {
        //    playerInputSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<InputSystem>();
        //    //playerTurningSystem = World.Active.GetOrCreateSystem<PlayerTurningSystem>();
        //    //playerAnimationSystem = World.Active.GetOrCreateSystem<PlayerAnimationSystem>();

        cameraFollowSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<CameraFollowSystem>();
        //movementSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<MovementSystem>();

    }


    private float mLastTime = 0;
    private int mLastMillisecond = 0;

    private void FixedUpdate()
    {
        //playerInputSystem.Update();
        //playerMovementSystem.Update();
        //playerTurningSystem.Update();
        //playerAnimationSystem.Update();

        if (cameraFollowSystem == null) cameraFollowSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<CameraFollowSystem>();
        //if (movementSystem == null) movementSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<MovementSystem>();

        cameraFollowSystem.Update();
        //movementSystem.Update();

        //Debug.Log("RunFixedUpdateSystems deltaTime: " + Time.deltaTime + " fixedDeltaTime: " + Time.fixedDeltaTime + " time: " + Time.time);
        Debug.Log("RunFixedUpdateSystems deltaTime: " + Time.deltaTime + " fixedDeltaTime: " + Time.fixedDeltaTime + " time: " + Time.time + " Diff: " + (Time.time - mLastTime) + " Now Millisecond Diff: " + Mathf.Abs(System.DateTime.Now.Millisecond - mLastMillisecond));
        mLastTime = Time.time;
        mLastMillisecond = System.DateTime.Now.Millisecond;
    }
}

camera follow system

using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;
using UnityEngine;

[DisableAutoCreation]
public class CameraFollowSystem : ComponentSystem
{
    private EntityQuery query;
    private float smoothing = 20f;
    private float3 offset = new float3(0, 2, -7);

    protected override void OnCreate()
    {
        query = GetEntityQuery(
            ComponentType.ReadOnly<LocalToWorld>(),
            ComponentType.ReadOnly<PlayerShipComponent>());
    }

    private double mLastTime = 0;
    private int mLastMillisecond = 0;

    protected override void OnUpdate()
    {
        var localToWorlds = query.ToComponentDataArray<LocalToWorld>(Unity.Collections.Allocator.TempJob);

        if (localToWorlds.Length > 0)
        {
            var dt = (float)(Time.ElapsedTime - mLastTime); // Time.DeltaTime;
         
            Entities.WithAllReadOnly<CameraComponent>().ForEach((ref Translation camPosition, ref Rotation camRotation) =>
            {
                var ltw = localToWorlds[0];
                var trans = ltw.Position;
                var rot = ltw.Rotation;

                var targetPos = trans + (math.mul(rot, offset));
                camPosition.Value = math.lerp(camPosition.Value, targetPos, smoothing * dt);

                var lookTo = math.normalize((trans + ltw.Forward * 100f) - camPosition.Value);
                var toRot = quaternion.LookRotation(lookTo, ltw.Up);
                camRotation.Value = math.slerp(camRotation.Value, toRot, smoothing * dt);
            });
            Debug.Log("Camera DeltaTime: " + Time.DeltaTime + " ElapsedTime: " + Time.ElapsedTime + " Diff: " + (Time.ElapsedTime - mLastTime) + " Now Millisecond Diff: " + math.abs(System.DateTime.Now.Millisecond - mLastMillisecond));
            mLastTime = Time.ElapsedTime;
            mLastMillisecond = System.DateTime.Now.Millisecond;
        }
        localToWorlds.Dispose();

    }
}