Game.Rendering.RelativeObjectSystem
Assembly: Game
Namespace: Game.Rendering
Type: public class RelativeObjectSystem
Base: GameSystemBase
Summary:
RelativeObjectSystem is a rendering/animation-focused ECS system used by the game to update entities that are positioned relative to other entities (Relative component). It integrates with the rendering & pre-culling pipeline and the animated system to:
- Compute world transforms for entities that are defined relative to a parent (e.g., props, passengers, sub-objects).
- Update interpolated transforms for smooth rendering/interpolation.
- Update and drive per-entity animations (including special driving animations and steering blending).
- Propagate transform updates down to nested sub-objects.
The system schedules two Burst-compiled jobs: UpdateRelativeTransformDataJob (parallel, deferred using PreCullingData index) and UpdateQueryTransformDataJob (IJobChunk) and wires job dependencies with PreCullingSystem and AnimatedSystem.
Fields
-
private RenderingSystem m_RenderingSystem
Reference to the global RenderingSystem used to obtain frame indices, frameTime, frameDelta, and frame LOD info. -
private PreCullingSystem m_PreCullingSystem
Reference to the PreCullingSystem used to read per-frame culling data (PreCullingData list). -
private AnimatedSystem m_AnimatedSystem
Reference to the AnimatedSystem used to set and write animation frames and obtain AnimationData. -
private CameraUpdateSystem m_CameraUpdateSystem
Reference to the camera updater; used to obtain camera position/direction and LOD parameters. -
private BatchDataSystem m_BatchDataSystem
Reference to the batch data system used to query level-of-detail information. -
private EntityQuery m_RelativeQuery
(Declared but not populated in OnCreate) potential query for relative objects. -
private EntityQuery m_InterpolateQuery
EntityQuery used when scheduling UpdateQueryTransformDataJob. Matches entities with Temp + Relative and (optionally) InterpolatedTransform, excluding Deleted. -
private uint m_PrevFrameIndex
Frame index for the previous update; used for interpolation/update-frame detection. -
private TypeHandle __TypeHandle
Internal struct storing ComponentLookup/BufferLookup/TypeHandle instances used to set up job data.
Properties
- None (no public properties exposed by this class).
Nested Types / Jobs (high level)
private struct UpdateRelativeTransformDataJob : IJobParallelForDefer
Burst-compiled parallel job that iterates over a NativeList(deferred indexing) and: - Filters pre-culling entries to those that are NearCamera, InterpolatedTransform and Relative.
- Resolves the parent entity (owner or current vehicle).
- Computes relative world transform using GetRelativeTransform (supports bone attachments and sub-mesh offsets).
- Updates InterpolatedTransform for the entity.
- If entity has animations, calculates update frames and updates interpolated animation frames via UpdateInterpolatedAnimations.
-
Recursively updates sub-object transforms (UpdateTransforms). Important data used: many ComponentLookup/BufferLookup handles (Owner, Relative, PrefabRef, BoneHistory, SubMesh, Animated, InterpolatedTransform, CullingInfo, etc.), random seed, animation data, camera/LOD params and PreCullingData.
-
private struct UpdateQueryTransformDataJob : IJobChunk
Burst-compiled IJobChunk that processes a chunk of entities: - For entities with InterpolatedTransform and certain Temp flags, computes transforms from owner (like in the parallel job) and resets animation state where needed.
- Copies transforms from original entity (Temp.m_Original) when appropriate.
- Initializes or synchronizes Animated buffers (animation indices, times) and sets animation frames via AnimatedSystem.AnimationData.SetAnimationFrame.
-
Updates sub-object transforms recursively. This job complements the deferred parallel job to ensure entities matched by the m_InterpolateQuery get consistent transforms/animation states.
-
private struct TypeHandle
Internal container of ComponentLookup/BufferLookup/EntityTypeHandle/SharedComponentTypeHandle/ComponentTypeHandle instances. It has a __AssignHandles(ref SystemState state) method used to bind the handles from the system state.
Constructors
public RelativeObjectSystem()
Default public constructor. The system uses OnCreate to obtain references to other systems and set up queries.
Methods
protected override void OnCreate()
Obtains references to other systems:- RenderingSystem, PreCullingSystem, AnimatedSystem, CameraUpdateSystem, BatchDataSystem.
-
Creates m_InterpolateQuery: All = Temp + Relative, Any = InterpolatedTransform, None = Deleted. Called when the system is created.
-
protected override void OnUpdate()
Core update that: - Requests culling data from PreCullingSystem (and its job dependency).
- Requests AnimationData writer from AnimatedSystem (and its dependency).
- Obtains camera position/direction and LOD parameters via CameraUpdateSystem (if available).
- Constructs UpdateRelativeTransformDataJob instance and schedules it over PreCullingData (deferred parallel).
- Schedules UpdateQueryTransformDataJob over m_InterpolateQuery (IJobChunk) with the deferred job as dependency.
- Passes resulting job handle to PreCullingSystem.AddCullingDataReader and AnimatedSystem.AddAnimationWriter; sets base.Dependency.
-
Updates m_PrevFrameIndex.
-
private static Transform GetRelativeTransform(Relative relative, Entity parent, ref BufferLookup<BoneHistory> boneHistoryLookup, ref ComponentLookup<PrefabRef> prefabRefLookup, ref BufferLookup<SubMesh> subMeshLookup)
Resolves the relative Transform of an entity: - If relative references a bone index, uses the bone history matrix to transform relative position & rotation.
- If additional sub-mesh offset index is present, applies sub-mesh position/rotation offset from the parent's prefab sub-meshes.
- Returns computed Transform (position + quaternion rotation).
-
Falls back to relative.m_Position/m_Rotation if bone index not valid.
-
public static void UpdateDrivingAnimationBody(Entity entity, in CharacterElement characterElement, DynamicBuffer<AnimationClip> clips, ref ComponentLookup<Human> humanLookup, ref BufferLookup<AnimationMotion> motionLookup, InterpolatedTransform oldTransform, InterpolatedTransform newTransform, ref Animated animated, ref Random random, float3 velocity, float steerAngle, AnimatedPropID propID, float updateFrameToSeconds, float speedDeltaFactor, float deltaTime, int updateFrameChanged, bool instantReset)
High-level driving animation logic for a character body: - Determines current activity (Driving vs Standing) based on forward velocity & steering.
- Chooses appropriate driving/steering animation clips and handles clip transitions/indices, interpolation and timing.
- Performs clip swapping when update frames indicate a change or when clip conditions require it.
-
Advances clip times based on deltaTime and whether movement speed slots are zero. This is a key static helper used by both jobs to update per-character driving animation states.
-
public static void UpdateDrivingClips(Entity entity, ref AnimationClip clip, ref AnimationClip clipI, ref short clipIndex, ref short clipIndexI, ref float movementSpeed, ref float interpolation, DynamicBuffer<AnimationClip> clips, ref ComponentLookup<Human> humanLookup, float steerAngle, AnimatedPropID propID, ActivityType targetActivity)
Helper used by UpdateDrivingAnimationBody: - Based on steerAngle selects appropriate left/right/idle animation types, finds clips using ObjectInterpolateSystem.FindAnimationClip, sets clip indices and interpolation values.
-
Handles clipI (steering helper clip for smooth transitions) and movementSpeed / interpolation parameters.
-
public static float GetTargetRotation(in AnimationClip clip, float def, float prev)
Returns the target rotation threshold for steer-based blending: - Uses clip.m_TargetValue if set, otherwise default def.
-
Ensures value is at least prev + 1 degree (in radians).
-
private void __AssignQueries(ref SystemState state)
Currently creates/disposes an empty EntityQueryBuilder (no queries assigned in this method). Used by OnCreateForCompiler path. -
protected override void OnCreateForCompiler()
Helper used by generated/compiled systems: -
Calls __AssignQueries and assigns component/buffer/type handles from __TypeHandle to the system state.
-
Misc (job Execute/UpdateTransforms)
The nested jobs implement many internal helpers: - UpdateTransforms(ownerTransform, subObjects) — recursively updates InterpolatedTransform for sub-objects that have Relative component, converting local-to-world transform using ObjectUtils.LocalToWorld.
- UpdateInterpolatedAnimations(...) — handles per-entity animation update when PreCullingFlags.Animated is set, including computing LOD priority and calling AnimatedSystem.AnimationData.SetAnimationFrame.
Usage Example
// This system is created/managed by the World. Example: get reference to the system and call a static helper.
var relSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystemManaged<Game.Rendering.RelativeObjectSystem>();
// Call a static helper directly (e.g., to compute a target rotation) — most interactions are internal to the ECS pipeline.
float targetRotation = Game.Rendering.RelativeObjectSystem.GetTargetRotation(myClip, math.radians(5f), 0f);
// Note: RelativeObjectSystem is intended to run inside the game's ECS update loop; user mods should generally not invoke its OnUpdate manually.
// If you want to influence behavior, modify components (Relative, Transform, Animated buffers, Temp flags, etc.) so the system processes entities naturally.
Notes / Implementation details ({{ YOUR_INFO }}): - The system heavily relies on PreCullingData flags to limit work to near-camera and relevant entities. PreCullingFlags used include NearCamera, InterpolatedTransform, Relative, Temp, Animated and NearCameraUpdated. - Bone attachments and sub-mesh offsets are supported: Relative entries can reference a bone (BoneHistory) and optionally a sub-mesh index from the parent's prefab to apply additional transform offsets. - Animation integration uses Animated buffers and AnimatedSystem.AnimationData to compute and set per-submesh/character animation frames. Characters with multiple SubMeshGroups use CharacterElement and style-based AnimationClip buffers. - The two main jobs are Burst-compiled for performance and are scheduled with proper job dependencies; the system registers readers/writers with PreCullingSystem and AnimatedSystem so these systems can manage proper synchronization. - Most methods and jobs assume many ComponentLookup/BufferLookup handles are set via the internal TypeHandle during system creation; modders should be careful when adding/removing components that could change query behavior.