Skip to content

Game.SubObjectReferencesSystem

Assembly: Game
Namespace: Game.Objects

Type: class

Base: GameSystemBase

Summary:
SubObjectReferencesSystem is an ECS system responsible for keeping owner entities' SubObject buffers in sync with sub-object entities. It scans all entities that have an Object and Owner components (and either Created or Deleted), but excludes Vehicles, Creatures and Secondary objects. For each matching entity chunk it runs a burst-compiled IJobChunk (UpdateSubObjectReferencesJob) that: - Removes sub-object references from an owner's SubObject buffer when the sub-object entity is marked Deleted. - Adds sub-object references to an owner's SubObject buffer when the sub-object entity is Created or marked Temp (and the owner has Temp component data). - Adds sub-object references in the normal (default) case for existing sub-objects.

This system uses ComponentTypeHandle/ComponentLookup/BufferLookup to perform chunked operations, leveraging Burst and the Unity Jobs system for performance. It's compiler-generated and preserved for runtime compatibility.


Fields

  • private EntityQuery m_ObjectQuery
    This query selects entities that represent sub-objects to be tracked:
  • All: Object (readonly), Owner (readonly)
  • Any: Created (readonly) OR Deleted (readonly)
  • None: Vehicle (readonly), Creature (readonly), Secondary (readonly) The query is required for update (RequireForUpdate) so the system only runs when relevant entities exist.

  • private TypeHandle __TypeHandle
    A private nested struct instance that stores all Entity/Component/Buffer handles the system needs. It provides an __AssignHandles(ref SystemState) helper to populate:

  • EntityTypeHandle
  • ComponentTypeHandle (readonly)
  • ComponentTypeHandle (readonly)
  • ComponentTypeHandle (readonly)
  • ComponentLookup (readonly)
  • BufferLookup (read/write) The system updates these handles before scheduling the job each frame.

  • private struct UpdateSubObjectReferencesJob (nested)
    Burst-compiled IJobChunk implementation that does the bulk of the work. Important fields:

  • m_EntityType : EntityTypeHandle (read-only)
  • m_OwnerType : ComponentTypeHandle (read-only)
  • m_DeletedType : ComponentTypeHandle (read-only)
  • m_TempType : ComponentTypeHandle (read-only)
  • m_TempData : ComponentLookup (read-only)
  • m_SubObjects : BufferLookup (read/write) Behavior summary:
  • If chunk has Deleted component: iterate entities and remove the sub-object Entity value from the owner's SubObject buffer.
  • Else if chunk has Temp component: add the sub-object to owner's SubObject buffer only if the owner has a Temp component (checked via ComponentLookup).
  • Else (normal case): add the sub-object to owner's SubObject buffer (TryAddUniqueValue ensures uniqueness). Internally uses CollectionUtils.RemoveValue and CollectionUtils.TryAddUniqueValue for buffer modifications.

  • private struct TypeHandle (nested)
    Holds strongly-typed handles for entity/component/buffer access and exposes __AssignHandles(ref SystemState) which populates them from the SystemState. This is how the generated system caches & refreshes handles in a safe way for Jobs.

Properties

  • None (this system does not expose public properties).
    Internally, component and buffer handles are stored in the private TypeHandle and passed into the job each update.

Constructors

  • public SubObjectReferencesSystem()
    Default constructor with [Preserve] attribute in the implementation. Initialization is done in OnCreate; constructor does not require additional parameters.

Methods

  • protected override void OnCreate()
    Initializes the m_ObjectQuery with the selection described above, and calls RequireForUpdate(m_ObjectQuery) so the system will only run when there are matching entities. Marked with [Preserve] in the source.

  • protected override void OnUpdate()
    Creates and populates an UpdateSubObjectReferencesJob instance by retrieving fresh Entity/Component/Buffer handles from the cached TypeHandle via InternalCompilerInterface.GetHandle/GetLookup helpers, then schedules the job over m_ObjectQuery using JobChunkExtensions.Schedule. The system sets base.Dependency to the returned JobHandle to chain dependencies.

  • protected override void OnCreateForCompiler()
    Compiler helper that calls __AssignQueries and __TypeHandle.__AssignHandles(ref base.CheckedStateRef). Ensures the generated type handles and query-related initialization occur correctly for the compiler-generated system.

  • private void __AssignQueries(ref SystemState state)
    Compiler-generated placeholder that currently only creates and disposes an EntityQueryBuilder(Allocator.Temp). Kept for compiler/linker compatibility.

  • private struct TypeHandle.__AssignHandles(ref SystemState state)
    Assigns the Entity/Component/Buffer handles used by the job from the provided SystemState.

  • private struct UpdateSubObjectReferencesJob.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
    Implements the job logic described in the Fields section. Also implements the explicit interface method IJobChunk.Execute that forwards to the same method.

Notes on threading and safety: - The job is Burst-compiled and runs on worker threads via the Job System. - BufferLookup is used to modify owner buffers; modifications rely on CollectionUtils helpers that ensure correct buffer operations. - ComponentLookup is used to check for an owner's Temp component in the Temp case; this is a random-access read on the main thread-safe lookup.

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    // Sets up the entity query so the system will run only when Object+Owner entities exist
    m_ObjectQuery = GetEntityQuery(new EntityQueryDesc {
        All = new ComponentType[] {
            ComponentType.ReadOnly<Object>(),
            ComponentType.ReadOnly<Owner>()
        },
        Any = new ComponentType[] {
            ComponentType.ReadOnly<Created>(),
            ComponentType.ReadOnly<Deleted>()
        },
        None = new ComponentType[] {
            ComponentType.ReadOnly<Vehicle>(),
            ComponentType.ReadOnly<Creature>(),
            ComponentType.ReadOnly<Secondary>()
        }
    });
    RequireForUpdate(m_ObjectQuery);
}

[Preserve]
protected override void OnUpdate()
{
    var job = new UpdateSubObjectReferencesJob {
        m_EntityType = InternalCompilerInterface.GetEntityTypeHandle(ref __TypeHandle.__Unity_Entities_Entity_TypeHandle, ref base.CheckedStateRef),
        m_OwnerType = InternalCompilerInterface.GetComponentTypeHandle(ref __TypeHandle.__Game_Common_Owner_RO_ComponentTypeHandle, ref base.CheckedStateRef),
        m_DeletedType = InternalCompilerInterface.GetComponentTypeHandle(ref __TypeHandle.__Game_Common_Deleted_RO_ComponentTypeHandle, ref base.CheckedStateRef),
        m_TempType = InternalCompilerInterface.GetComponentTypeHandle(ref __TypeHandle.__Game_Tools_Temp_RO_ComponentTypeHandle, ref base.CheckedStateRef),
        m_TempData = InternalCompilerInterface.GetComponentLookup(ref __TypeHandle.__Game_Tools_Temp_RO_ComponentLookup, ref base.CheckedStateRef),
        m_SubObjects = InternalCompilerInterface.GetBufferLookup(ref __TypeHandle.__Game_Objects_SubObject_RW_BufferLookup, ref base.CheckedStateRef)
    };
    base.Dependency = JobChunkExtensions.Schedule(job, m_ObjectQuery, base.Dependency);
}

Additional notes for modders: - This system runs at the ECS level; to ensure your custom objects are processed, make sure entities have the expected components (Object, Owner) and appropriate Created/Deleted flags. - Owner entities must have a dynamic buffer present to receive references — the system uses BufferLookup to add/remove entries. - When adding sub-objects in custom systems or authoring code, prefer adding Created/Temp components as appropriate; the SubObjectReferencesSystem will then reconcile buffers on the next update. - Because the job uses TryAddUniqueValue semantics, duplicate sub-object entries are prevented. - This system excludes Vehicles, Creatures, and Secondary-tagged objects: if you want sub-object relations for those types, you'll need to modify or create a separate system.