Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Suggestion / Idea  ECS Physics/Graphics Support
#18
I only got back to this the last hour; but it seems to work doing it manual mode with inspiration of what you said. (Also posting it for any future ECSer)

Code:
public struct ObiRuntimeData : IComponentData
{
    public NetworkTick lastFixedTick;
    public double elapsedTime;
    public float deltaTime;
}

[BurstCompile]
[UpdateInGroup(typeof(PredictedFixedStepSimulationSystemGroup), OrderFirst = true)]
[WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation)]
public partial struct RecordLastPredictedFixedTickForObiSystem : ISystem
{
    [BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        SystemAPI.TryGetSingleton<NetworkTime>(out var networkTime);
        if (!networkTime.IsFinalFullPredictionTick)
        {
            return;
        }
       
        ref var obiRuntimeData = ref SystemAPI.GetSingletonRW<ObiRuntimeData>().ValueRW;
        obiRuntimeData.lastFixedTick = networkTime.ServerTick;
        obiRuntimeData.elapsedTime = SystemAPI.Time.ElapsedTime;
        obiRuntimeData.deltaTime = SystemAPI.Time.DeltaTime;
    }
}

[UpdateInGroup(typeof(SimulationSystemGroup), OrderLast = true)] // Seems ObiBones write back in LateUpdate, so can't have in PresentationGroup
[WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation)]
public partial struct ObiManualUpdateSystem : ISystem
{
    private NetworkTick _lastFixedTick;
    public void OnCreate(ref SystemState state)
    {
        state.RequireForUpdate<ClientServerTickRate>();
        state.EntityManager.CreateSingleton<ObiRuntimeData>();
    }

    public void OnUpdate(ref SystemState state)
    {
        var system = state.World.GetExistingSystemManaged<GhostPresentationGameObjectSystem>();
       
        SystemAPI.TryGetSingleton<ObiRuntimeData>(out var obiRuntimeData);
        var timeAhead = (float)(SystemAPI.Time.ElapsedTime - obiRuntimeData.elapsedTime);
        var timeStep = (float)obiRuntimeData.deltaTime;
        if (timeAhead < 0f || timeStep == 0f)
        {
            return;
        }
       
        // Assumption we do 1:1 physics ticks with tick rate
        var steps = _lastFixedTick.IsValid ? obiRuntimeData.lastFixedTick.TicksSince(_lastFixedTick) : 1;
        _lastFixedTick = obiRuntimeData.lastFixedTick;
       
        foreach (var (_, localTransformRef, entity) in SystemAPI.Query<RefRW<ObiSolverData>, RefRO<LocalTransform>>().WithEntityAccess())
        {
            var gameObject = system.GetGameObjectForEntity(state.EntityManager, entity);
            var obiSolver = gameObject?.GetComponent<ObiSolver>();
            if (obiSolver == null)
            {
                continue;
            }
#if UNITY_EDITOR
            if (obiSolver.isActiveAndEnabled)
            {
                Debug.LogError($"ObiSolver {gameObject.name} is enabled but running in manual mode. Please disable the component to avoid unexpected behavior.", gameObject);
            }
#endif
           
            // Use localTransform for fixed updated position compared to transform (which is updated from localToWorld)
            var interpolatedLocalPosition = gameObject.transform.localPosition;
            var interpolatedLocalRotation = gameObject.transform.localRotation;
           
            gameObject.transform.localPosition = localTransformRef.ValueRO.Position;
            gameObject.transform.localRotation = localTransformRef.ValueRO.Rotation;
           
            if (steps > 0)
            {
                obiSolver.StartSimulation(timeStep, steps);
            }
            obiSolver.Render(timeAhead);
           
            gameObject.transform.localPosition = interpolatedLocalPosition;
            gameObject.transform.localRotation = interpolatedLocalRotation;
        }
    }
}

I think the only thing now that I need to modify the asset now for is to add a setting to be able to scale the inertia wind when set in World mode, which might be a nice setting to have in general. For reference; the code below `ApplyInertialForcesJob`.

Code:
            if (inertialWind)
            {
                float4 wsPos = inertialFrame.frame.TransformPoint(positions[i]);
                wind[i] -= inertialFrame.frame.InverseTransformVector(inertialFrame.VelocityAtPoint(wsPos));
            }
Reply


Messages In This Thread
ECS Physics/Graphics Support - by Jawsarn - 23-04-2026, 09:29 PM
RE: ECS Physics/Graphics Support - by josemendez - 24-04-2026, 08:39 AM
RE: ECS Physics/Graphics Support - by Jawsarn - 25-04-2026, 10:49 PM
RE: ECS Physics/Graphics Support - by josemendez - 27-04-2026, 09:00 AM
RE: ECS Physics/Graphics Support - by Jawsarn - 27-04-2026, 09:45 PM
RE: ECS Physics/Graphics Support - by Jawsarn - 07-05-2026, 09:49 AM
RE: ECS Physics/Graphics Support - by josemendez - 07-05-2026, 10:34 AM
RE: ECS Physics/Graphics Support - by Jawsarn - 07-05-2026, 02:29 PM
RE: ECS Physics/Graphics Support - by josemendez - 07-05-2026, 03:22 PM
RE: ECS Physics/Graphics Support - by Jawsarn - 07-05-2026, 05:42 PM
RE: ECS Physics/Graphics Support - by josemendez - 07-05-2026, 06:36 PM
RE: ECS Physics/Graphics Support - by Jawsarn - 07-05-2026, 07:29 PM
RE: ECS Physics/Graphics Support - by josemendez - 08-05-2026, 08:50 AM
RE: ECS Physics/Graphics Support - by Jawsarn - 08-05-2026, 08:54 AM
RE: ECS Physics/Graphics Support - by josemendez - 08-05-2026, 09:02 AM
RE: ECS Physics/Graphics Support - by Jawsarn - 08-05-2026, 09:17 AM
RE: ECS Physics/Graphics Support - by josemendez - 08-05-2026, 11:21 AM
RE: ECS Physics/Graphics Support - by Jawsarn - 15-05-2026, 04:16 PM
RE: ECS Physics/Graphics Support - by Jawsarn - 16-05-2026, 07:46 PM
RE: ECS Physics/Graphics Support - by josemendez - 17-05-2026, 09:21 AM
RE: ECS Physics/Graphics Support - by Jawsarn - 17-05-2026, 12:02 PM
RE: ECS Physics/Graphics Support - by josemendez - 20-05-2026, 02:00 PM
RE: ECS Physics/Graphics Support - by Jawsarn - 18-08-2026, 10:13 AM
RE: ECS Physics/Graphics Support - by josemendez - 22-08-2026, 10:26 AM