Skip to content

Game.Routes.SearchSystem

Assembly: Assembly-CSharp (game binary)
Namespace: Game.Routes

Type: class

Base: GameSystemBase, IPreDeserialize

Summary:
SearchSystem maintains a spatial search index (NativeQuadTree) for route-related entities (waypoints and curve/segment elements). It listens for created/updated/deleted events on route entities and updates the quad-tree accordingly, allowing other systems/jobs to query route geometry efficiently. It also exposes methods to coordinate read/write dependency handling for concurrent jobs and resets the tree during deserialization.


Fields

  • private EntityQuery m_UpdatedRoutesQuery
    Holds an EntityQuery that selects route entities that have been updated/created/deleted (or path elements/segments/events that indicate changes). Used in OnUpdate to find which entities need tree updates.

  • private EntityQuery m_AllRoutesQuery
    Holds an EntityQuery that selects all non-temp route entities (used when the system is in a "loaded" state to rebuild the entire tree).

  • private NativeQuadTree<RouteSearchItem, QuadTreeBoundsXZ> m_SearchTree
    The primary spatial index storing route search items and their bounds. Allocated with Allocator.Persistent in OnCreate and disposed in OnDestroy.

  • private NativeParallelHashMap<Entity, int> m_ElementCount
    Maps an entity to the count of curve/segment elements indexed for that entity. Used to track how many element entries exist for removal/update logic.

  • private JobHandle m_ReadDependencies
    Aggregates job handles of jobs that read the search tree. Used to coordinate safe concurrent access.

  • private JobHandle m_WriteDependencies
    Holds the job handle of the job that last wrote to the search tree. Used together with m_ReadDependencies to determine when the tree is safe to read or write.

  • private bool m_Loaded
    Flag set during PreDeserialize to indicate the next OnUpdate should treat the query as a full reload (rebuild/search-tree population).

  • private TypeHandle __TypeHandle
    Internal container for EntityTypeHandle / ComponentTypeHandle / BufferTypeHandle / ComponentLookup / BufferLookup instances used by the UpdateSearchTreeJob. Assigned on system creation for fast access.

Properties

  • This class does not expose public properties.

Constructors

  • public SearchSystem()
    Default constructor (preserved). The real initialization occurs in the OnCreate override where queries and native collections are created.

Methods

  • protected override void OnCreate()
    Initializes entity queries used for incremental and full updates, creates the NativeQuadTree (m_SearchTree) and NativeParallelHashMap (m_ElementCount). Queries include criteria for Waypoint/Position, Segment/PathElement and events/path-updated components. Called by the ECS bootstrap.

  • protected override void OnDestroy()
    Disposes m_SearchTree and m_ElementCount and calls base.OnDestroy(). Ensures native containers are released when the system is destroyed.

  • private bool GetLoaded()
    Internal helper used in OnUpdate. If m_Loaded is true, it clears the flag and returns true (indicating that the next update should treat queries as a full load). Otherwise returns false.

  • protected override void OnUpdate()
    Main update loop. Chooses either the incremental (m_UpdatedRoutesQuery) or full (m_AllRoutesQuery) query depending on GetLoaded(). If the chosen query isn't empty, it constructs an UpdateSearchTreeJob with all required handles and lookups, retrieves the search tree via GetSearchTree(readOnly: false, out dependencies), schedules the job over the query (JobChunk schedule) and records the write dependency via AddSearchTreeWriter. The job updates, adds or removes entries in the quad-tree depending on entity state (created/updated/deleted/path-updated).

  • public NativeQuadTree<RouteSearchItem, QuadTreeBoundsXZ> GetSearchTree(bool readOnly, out JobHandle dependencies)
    Returns the internal quad-tree. Also outputs current combined JobHandle dependencies:

  • If readOnly is true, dependencies = m_WriteDependencies (so readers wait for writers).
  • If readOnly is false, dependencies = JobHandle.CombineDependencies(m_ReadDependencies, m_WriteDependencies) (writers must wait for prior readers/writers). This method is how other systems/jobs obtain a reference to the search tree and the dependencies they must respect.

  • public void AddSearchTreeReader(JobHandle jobHandle)
    Registers a job that reads the search tree by combining jobHandle into m_ReadDependencies. This prevents a writer from proceeding until all readers complete.

  • public void AddSearchTreeWriter(JobHandle jobHandle)
    Registers a writer job by setting m_WriteDependencies to jobHandle. Writers will be combined appropriately by GetSearchTree when needed.

  • public void PreDeserialize(Context context)
    Called before deserialization (implements IPreDeserialize). Completes any outstanding dependencies for writing the tree, clears the search tree, and sets m_Loaded = true so the next update rebuilds the tree from all route entities.

  • private void __AssignQueries(ref SystemState state)
    Internal/compiled helper (used by OnCreateForCompiler). Present as part of codegen; in this file it only creates/cleans an EntityQueryBuilder placeholder but should not be used directly.

  • protected override void OnCreateForCompiler()
    Compiler helper which calls __AssignQueries and assigns the component type handles via __TypeHandle.__AssignHandles. Used in compiled environment to satisfy generated code expectations.

Nested types / Jobs

  • private struct TypeHandle
    Contains precomputed EntityTypeHandle, ComponentTypeHandle (read-only), BufferTypeHandle, ComponentLookup, and BufferLookup. Has a method __AssignHandles(ref SystemState state) to populate all handles for the current SystemState.

  • public struct UpdateSearchTreeJob : IJobChunk (BurstCompile)
    This is the job that performs the heavy work of adding/updating/removing entries in the native quad-tree. Important behaviors:

  • Fields: various ReadOnly type handles (EntityTypeHandle, ComponentTypeHandle, Created, Deleted, PrefabRef, PathUpdated, BufferTypeHandle) and ComponentLookup/BufferLookup instances, plus m_Loaded flag, m_SearchTree (NativeQuadTree) and m_ElementCount (NativeParallelHashMap).
  • Execute(in ArchetypeChunk chunk, ...) inspects chunk component state:
    • If chunk has PathUpdated: iterates PathUpdated elements and selectively updates segments in the tree if segment present and not temp/updated/deleted.
    • Else if m_Loaded or chunk has Created: adds entries for waypoint positions and curve elements to the tree (calculates Bounds3 via RouteUtils.CalculateBounds using RouteData).
    • Else if chunk has Deleted: removes waypoint entry and all element entries for that entity (uses m_ElementCount to know how many to remove).
    • Else (normal update): updates bounds for entity's waypoint and its curve elements; uses UpdateSegment helper to add/update/remove per-element entries and maintain m_ElementCount.
  • UpdateSegment(Entity, PrefabRef, DynamicBuffer) helper updates per-element quad-tree entries for a segment; it reconciles the new element count with previous count (m_ElementCount) and adds/updates/removes entries accordingly.
  • The IJobChunk.Execute wrapper calls the typed Execute to satisfy the interface.

Notes about thread-safety and usage: - The job writes to m_SearchTree and m_ElementCount so callers must obtain the tree via GetSearchTree(readOnly:false, out deps) prior to scheduling jobs that will use it, and must register writers/readers via AddSearchTreeWriter/AddSearchTreeReader so the system can coordinate dependencies. - The UpdateSearchTreeJob is Burst-compiled and uses ComponentTypeHandle/BufferTypeHandle/ComponentLookup/BufferLookup for efficient chunk iteration. - Route bounds are computed via RouteUtils.CalculateBounds using RouteData looked up from a PrefabRef.

Usage Example

// Example: read the search tree safely from another system or job
var searchSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem<SearchSystem>();
if (searchSystem != null)
{
    JobHandle deps;
    var tree = searchSystem.GetSearchTree(readOnly: true, out deps);

    // If you need immediate (synchronous) access:
    deps.Complete();

    // Now 'tree' can be queried on the main thread (or used to build job data).
    // If you schedule a job that reads the tree, register it:
    // searchSystem.AddSearchTreeReader(myReaderJobHandle);
}

If you need to force a full rebuild after loading/deserialization, SearchSystem.PreDeserialize is invoked by the runtime to clear the tree and mark a full reload on the next update.