Skip to content

Game.Objects.UpdateCollectSystem

Assembly:
Namespace: Game.Objects

Type: class

Base: GameSystemBase

Summary:
UpdateCollectSystem collects and exposes 2D bounds (Bounds2) of objects that were Created, Updated or Deleted during a frame. It queries object entities (Object + Static + Transform + PrefabRef) and uses a combination of a static search tree and prefab geometry to compute the bounds. Work is performed with Burst-compiled jobs (IJobChunk and IJob), using a NativeQueue to gather results on worker threads and a NativeList to store the final list of updated bounds for other systems to consume. The system also exposes dependency handles so other jobs can safely read those bounds.


Fields

  • private Unity.Entities.EntityQuery m_ObjectQuery
    Holds the entity query used to find object entities to inspect. Query All: Object, Static, Transform, PrefabRef. Any: Created, Updated, Deleted. None: Temp.

  • private SearchSystem m_SearchSystem
    Reference to the SearchSystem used to read the static search tree (static object bounds) for existing entities.

  • private Unity.Collections.NativeList<Bounds2> m_UpdatedBounds
    Persistent NativeList that stores the final list of updated Bounds2 produced by the system each frame. Returned to callers via GetUpdatedBounds.

  • private Unity.Jobs.JobHandle m_WriteDependencies
    JobHandle representing the most recent writer dependency (jobs that produced/wrote m_UpdatedBounds). Returned by GetUpdatedBounds as the dependencies that consumers must wait on.

  • private Unity.Jobs.JobHandle m_ReadDependencies
    Aggregated JobHandle of reader dependencies that this system should wait for before producing new data (consumers can add their read handles with AddBoundsReader).

  • private TypeHandle __TypeHandle
    Internal container of the various EntityTypeHandle / ComponentTypeHandle / ComponentLookup used by the jobs. Populated in __AssignHandles.

Properties

  • public bool isUpdated { get; private set; }
    True while the system has been updated this frame (set to true at start of OnUpdate). Cleared to false in OnStopRunning. Can be used to quickly check whether the system collected any bounds this runtime frame.

Constructors

  • public UpdateCollectSystem()
    Default constructor (empty). System initialization is performed in OnCreate.

Methods

  • protected override void OnCreate() : System.Void
    Initializes the system: acquires a reference to SearchSystem, creates the entity query for objects, allocates m_UpdatedBounds (Allocator.Persistent), and calls RequireForUpdate(m_ObjectQuery) so the system runs only when matching entities exist.

  • protected override void OnDestroy() : System.Void
    Disposes m_UpdatedBounds and calls base.OnDestroy().

  • protected override void OnStopRunning() : System.Void
    Completes outstanding write/read dependencies, clears m_UpdatedBounds, sets isUpdated = false, and calls base.OnStopRunning().

  • protected override void OnUpdate() : System.Void
    Main runtime logic:

  • Sets isUpdated = true.
  • Creates a NativeQueue (TempJob) for workers to enqueue computed bounds.
  • Prepares and schedules a Burst-compiled IJobChunk (CollectUpdatedObjectBoundsJob) that:
    • For Created entities: computes bounds from prefab geometry (ObjectGeometryData + ObjectUtils.CalculateBounds) and enqueues them.
    • For Deleted entities: looks up existing bounds in the SearchSystem tree and enqueues them.
    • For Updated entities: attempts to read both existing bounds (from search tree) and recomputed bounds (from prefab geometry), then either enqueues the merged bounds or both parts depending on overlap/size logic.
    • Uses m_SearchSystem.GetStaticSearchTree(readOnly: true, out dependencies) to obtain the static tree and producer dependencies.
  • Schedules a DequeueBoundsJob (IJob) that transfers queued Bounds2 from the NativeQueue into the persistent m_UpdatedBounds NativeList.
  • Disposes the queue with the combined dependency of the Dequeue job.
  • Adds the Collect job as a static search tree reader (m_SearchSystem.AddStaticSearchTreeReader(jobHandle)) so readers are tracked.
  • Updates m_WriteDependencies and base.Dependency to chain further work correctly.

  • public NativeList<Bounds2> GetUpdatedBounds(out Unity.Jobs.JobHandle dependencies) : NativeList
    Returns the NativeList containing the updated bounds and outputs the JobHandle (m_WriteDependencies) that consumers must complete before reading the list.

  • public void AddBoundsReader(Unity.Jobs.JobHandle handle) : System.Void
    Allows external code to add a read dependency that this system will combine into m_ReadDependencies. This ensures the system waits for provided readers before modifying or producing new data.

  • protected override void OnCreateForCompiler() : System.Void
    Compiler helper used to assign queries and type handles (calls __AssignQueries and __TypeHandle.__AssignHandles). Present for generated/compiled compatibility.

  • private void __AssignQueries(ref Unity.Entities.SystemState state) : System.Void
    Internal method used by the compiler flow. In this class it creates an EntityQueryBuilder (temporary) and disposes it; real handles are assigned in __AssignHandles.

Nested/Burst jobs (high level):

  • CollectUpdatedObjectBoundsJob : IJobChunk (BurstCompile)
  • Read-only handles: EntityTypeHandle, Transform, PrefabRef, Created, Deleted, ComponentLookup.
  • Read-only NativeQuadTree m_SearchTree (retrieved from SearchSystem).
  • NativeQueue.ParallelWriter m_ResultQueue used to push results from worker threads.
  • Logic:

    • If chunk has Created: iterate PrefabRef+Transform, compute geometry bounds from ObjectGeometryData (if present) and enqueue their xz bounds.
    • Else if chunk has Deleted: iterate Entities, lookup existing bounds in m_SearchTree and enqueue stored xz bounds.
    • Else (Updated): for each entity try to get existing bounds from m_SearchTree and compute new prefab geometry bounds if available; combine them:
    • If both exist: compute union and if the union's size is less than sum of parts (i.e., overlapping) enqueue the union; otherwise enqueue both separately.
    • If only existing or only computed bounds exist, enqueue the one present.
  • DequeueBoundsJob : IJob (BurstCompile)

  • Pulls all entries from a NativeQueue and writes them into a NativeList (m_UpdatedBounds). Uses ResizeUninitialized(count) then populates the list.

Notes and implementation details: - Uses BurstCompile on the jobs for performance. - Uses NativeQueue.AsParallelWriter to allow the IJobChunk to enqueue from worker threads. - Prefab geometry is obtained via ComponentLookup and ObjectUtils.CalculateBounds which returns a Bounds3; only the XZ projection (Bounds2) is stored/used by this system. - The SearchSystem provides a static search tree containing previously indexed object bounds; the system uses that tree to read existing bounds for Deleted/Updated handling. - Memory ownership: m_UpdatedBounds is allocated with Allocator.Persistent and must be disposed in OnDestroy. The temporary queue is Allocator.TempJob and disposed via queue.Dispose(jobHandle). - Synchronization: callers must use the JobHandle returned by GetUpdatedBounds to ensure the list is ready for reading, or call AddBoundsReader to add their read jobs into the system's read dependency chain.

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    m_SearchSystem = base.World.GetOrCreateSystemManaged<SearchSystem>();
    m_ObjectQuery = GetEntityQuery(new EntityQueryDesc
    {
        All = new ComponentType[4]
        {
            ComponentType.ReadOnly<Object>(),
            ComponentType.ReadOnly<Static>(),
            ComponentType.ReadOnly<Transform>(),
            ComponentType.ReadOnly<PrefabRef>()
        },
        Any = new ComponentType[3]
        {
            ComponentType.ReadOnly<Created>(),
            ComponentType.ReadOnly<Updated>(),
            ComponentType.ReadOnly<Deleted>()
        },
        None = new ComponentType[1] { ComponentType.ReadOnly<Temp>() }
    });
    m_UpdatedBounds = new NativeList<Bounds2>(Allocator.Persistent);
    RequireForUpdate(m_ObjectQuery);
}

Additional quick example (reading updated bounds safely):

// Somewhere after UpdateCollectSystem runs:
var updatedBounds = updateCollectSystem.GetUpdatedBounds(out JobHandle produceDeps);
// If scheduling a job that reads updatedBounds, combine its handle and then call:
// updateCollectSystem.AddBoundsReader(readerJobHandle);
// Ensure to complete produceDeps before directly reading the NativeList on the main thread.