Skip to content

Game.TransformFrameSystem

Assembly: Game (inferred from namespace)
Namespace: Game.Serialization

Type: class

Base: GameSystemBase

Summary:
TransformFrameSystem is an ECS system responsible for preparing interpolation data for moving entities. It collects current Transform and Moving-related components in chunks, updates an InterpolatedTransform component, and maintains a 4-slot circular/history buffer of TransformFrame records used by rendering/interpolation. The system computes an update-frame offset using the SimulationSystem.frameIndex to back-extrapolate positions based on velocity so interpolation produces smooth movement across simulation/render frames. The heavy work is performed in a Burst-compiled IJobChunk (TransformFrameJob) for performance.


Fields

  • private SimulationSystem m_SimulationSystem
    Holds a reference to the SimulationSystem instance from the World. The job uses the SimulationSystem.frameIndex (copied into the job) to compute the update-frame offset for back-extrapolation.

  • private EntityQuery m_Query
    EntityQuery that selects entities having TransformFrame buffer, InterpolatedTransform and a Transform component. The system requires this query to run (RequireForUpdate).

  • private TypeHandle __TypeHandle
    Container for component type handles used by the job. __TypeHandle.__AssignHandles(ref SystemState) initializes SharedComponentTypeHandle, ComponentTypeHandles and BufferTypeHandle used when scheduling the job.

Additionally, the class defines two nested types:

  • Burst-compiled private struct TransformFrameJob : IJobChunk
  • Performs chunked processing. Reads UpdateFrame (shared component), Transform, Moving, optional HumanNavigation/AnimalNavigation, optional Train and writes InterpolatedTransform and a DynamicBuffer. It:
    • Copies the current Transform into InterpolatedTransform.
    • Ensures the TransformFrame buffer has 4 frames (resizes if necessary).
    • Computes a TransformFlags value (e.g., Pantograph flag for trains).
    • Calls InitTransformFrames to fill each buffer frame, doing a back-extrapolation of position by velocity using a fixed seconds-per-frame (4/15) and an offset that depends on the simulation frame index.
    • Handles per-entity variants depending on presence of HumanNavigation, AnimalNavigation, or neither.
  • Private helper InitTransformFrames applies either a full reset (when the buffer length changed) or updates existing frames, then subtracts velocity*lagSeconds to create historical frames.

  • private struct TypeHandle

  • Holds type handles:
    • SharedComponentTypeHandle
    • ComponentTypeHandle (ReadOnly)
    • ComponentTypeHandle (ReadOnly)
    • ComponentTypeHandle (ReadOnly)
    • ComponentTypeHandle (ReadOnly)
    • ComponentTypeHandle (ReadOnly)
    • ComponentTypeHandle (ReadWrite)
    • BufferTypeHandle (ReadWrite)
  • __AssignHandles method sets these up from a SystemState.

Properties

  • This system exposes no public properties.

Constructors

  • public TransformFrameSystem()
    Default constructor. Marked with [Preserve] attribute to keep it available to Unity's managed code stripping. No runtime initialization is performed here beyond what base class does.

Methods

  • protected override void OnCreate()
    Marked with [Preserve]. Called when the system is created. Implementation:
  • Calls base.OnCreate().
  • Acquires the SimulationSystem instance via World.GetOrCreateSystemManaged() and stores it in m_SimulationSystem.
  • Creates an EntityQuery that matches ComponentType.ReadWrite(), ComponentType.ReadWrite(), ComponentType.ReadOnly() and stores it in m_Query.
  • Calls RequireForUpdate(m_Query) so the system only runs when there are matching entities.

  • protected override void OnUpdate()
    Marked with [Preserve]. Called each frame if the query yields entities. Implementation:

  • Constructs a TransformFrameJob instance, initializing its component type handles by calling InternalCompilerInterface.GetSharedComponentTypeHandle / GetComponentTypeHandle / GetBufferTypeHandle with the stored __TypeHandle handles and the system's checked state reference.
  • Sets jobData.m_SimulationFrameIndex = m_SimulationSystem.frameIndex so the job can compute updateFrameOffset.
  • Schedules the job with JobChunkExtensions.ScheduleParallel(jobData, m_Query, base.Dependency) and assigns the returned JobHandle back to base.Dependency.
  • The job is Burst-compiled and runs in parallel over chunks.

  • protected override void OnCreateForCompiler()
    Called by generated code to set up internal bookkeeping for the system in compilation contexts:

  • Calls __AssignQueries(ref base.CheckedStateRef) and __TypeHandle.__AssignHandles(ref base.CheckedStateRef).

  • private void __AssignQueries(ref SystemState state)
    Small helper used in generated-on-compiler initialization. In this implementation it constructs and disposes an empty EntityQueryBuilder (no side effects here).

  • private struct TypeHandle.__AssignHandles(ref SystemState state)
    Initializes all the contained SharedComponentTypeHandle / ComponentTypeHandle / BufferTypeHandle instances from the supplied SystemState.

  • private struct TransformFrameJob.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
    Main chunk processing entry point for the job. See details under Fields (TransformFrameJob).

  • private void TransformFrameJob.InitTransformFrames(Transform transform, Moving moving, TransformState state, TransformFlags flags, byte activity, DynamicBuffer<TransformFrame> transformFrames, uint updateFrameOffset, bool fullReset)
    Helper used by the job to initialize or update the 4-element TransformFrame buffer for a single entity, applying back-extrapolation by velocity. Uses a seconds-per-frame constant of 4f/15f and adds 2f/15f to compute per-slot lag.

Notes about internal behavior and constants: - The job uses a circular/history buffer of length 4 for TransformFrame objects. If the buffer length isn't 4 it resizes and performs a full reset of frame contents. - SECONDS_PER_FRAME is implemented as 4f / 15f in the job. The per-slot lag is computed as ((updateFrameOffset - slotIndex) % 4) * SECONDS_PER_FRAME + 2f/15f. - Train pantograph state is recorded via TransformFlags.Pantograph if the Train component has the Pantograph flag. - The job carefully handles combinations of components (Moving alone, Moving+HumanNavigation, Moving+AnimalNavigation, no Moving) to populate frames appropriately.

Usage Example

Demonstrates how the system initializes and schedules the job (this mirrors the behavior in the class):

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    // Acquire the SimulationSystem to obtain the global simulation frame index
    m_SimulationSystem = base.World.GetOrCreateSystemManaged<SimulationSystem>();

    // Ensure system only updates when relevant components exist
    m_Query = GetEntityQuery(
        ComponentType.ReadWrite<TransformFrame>(),
        ComponentType.ReadWrite<InterpolatedTransform>(),
        ComponentType.ReadOnly<Transform>()
    );
    RequireForUpdate(m_Query);
}

[Preserve]
protected override void OnUpdate()
{
    var jobData = new TransformFrameJob
    {
        m_UpdateFrameType = InternalCompilerInterface.GetSharedComponentTypeHandle(ref __TypeHandle.__Game_Simulation_UpdateFrame_SharedComponentTypeHandle, ref base.CheckedStateRef),
        m_TransformType = InternalCompilerInterface.GetComponentTypeHandle(ref __TypeHandle.__Game_Objects_Transform_RO_ComponentTypeHandle, ref base.CheckedStateRef),
        m_MovingType = InternalCompilerInterface.GetComponentTypeHandle(ref __TypeHandle.__Game_Objects_Moving_RO_ComponentTypeHandle, ref base.CheckedStateRef),
        m_HumanNavigationType = InternalCompilerInterface.GetComponentTypeHandle(ref __TypeHandle.__Game_Creatures_HumanNavigation_RO_ComponentTypeHandle, ref base.CheckedStateRef),
        m_AnimalNavigationType = InternalCompilerInterface.GetComponentTypeHandle(ref __TypeHandle.__Game_Creatures_AnimalNavigation_RO_ComponentTypeHandle, ref base.CheckedStateRef),
        m_TrainType = InternalCompilerInterface.GetComponentTypeHandle(ref __TypeHandle.__Game_Vehicles_Train_RO_ComponentTypeHandle, ref base.CheckedStateRef),
        m_InterpolatedTransformType = InternalCompilerInterface.GetComponentTypeHandle(ref __TypeHandle.__Game_Rendering_InterpolatedTransform_RW_ComponentTypeHandle, ref base.CheckedStateRef),
        m_TransformFrameType = InternalCompilerInterface.GetBufferTypeHandle(ref __TypeHandle.__Game_Objects_TransformFrame_RW_BufferTypeHandle, ref base.CheckedStateRef),
        m_SimulationFrameIndex = m_SimulationSystem.frameIndex
    };

    base.Dependency = JobChunkExtensions.ScheduleParallel(jobData, m_Query, base.Dependency);
}

Additional notes for modders: - This system is performance-sensitive and uses Burst and IJobChunk. If you modify the job, ensure Burst compatibility and keep the memory access patterns cache-friendly. - The 4-frame history and the specific seconds-per-frame arithmetic are tuned for the game's interpolation between simulation and rendering; changing these values will affect perceived smoothing of movement. - The system expects TransformFrame buffer elements and InterpolatedTransform components to exist on entities. If you add new entity archetypes that should be handled, ensure they include those components and, where applicable, Moving/HumanNavigation/AnimalNavigation/Train components.