Skip to content

Game.Serialization.LaneObjectSystem

Assembly: Assembly-CSharp (game assembly)
Namespace: Game.Serialization

Type: class

Base: GameSystemBase

Summary:
LaneObjectSystem is a managed ECS system responsible for collecting "lane objects" (vehicles, humans, animals, parked objects, blocked-lane markers, etc.) each frame and either adding them to per-lane buffers (LaneObject buffers) or inserting them into the global moving-object search tree. The system schedules a Burst-compiled IJobChunk (LaneObjectJob) that iterates archetype chunks containing any of the lane-related components and performs the following main tasks: - For entities that have lane buffers for their current lanes, it adds a LaneObject entry to that lane's DynamicBuffer using NetUtils.AddLaneObject. - For entities that do not belong to a lane buffer (for example flying aircraft or objects without a lane) it computes object bounds (using Transform + PrefabRef geometry data) and adds the entity to the moving search tree for spatial queries. - Handles special cases for trailers, trains (front/rear positions), parked vehicles/trains, blocked lanes, and lane-change lanes. The job is Burst-compiled and uses a moving search tree obtained from Game.Objects.SearchSystem. The system registers itself as a writer to the moving search tree so the tree is updated safely with the job's results.


Fields

  • private Game.Objects.SearchSystem m_ObjectSearchSystem
    Holds a reference to the SearchSystem used to obtain the moving search tree that stores entities not attached to a lane buffer.

  • private EntityQuery m_Query
    EntityQuery used to select entities that contain any of the lane-related components (CarCurrentLane, CarTrailerLane, ParkedCar, ParkedTrain, WatercraftCurrentLane, AircraftCurrentLane, TrainCurrentLane, HumanCurrentLane, AnimalCurrentLane, BlockedLane). Required for update.

  • private TypeHandle __TypeHandle
    Container for the Component/Entity type handles used by the job. It contains read-only handles for the various current-lane components, buffer types and lookups, and provides an __AssignHandles(ref SystemState) helper used by OnCreateForCompiler().

  • private struct LaneObjectJob (nested)
    Burst-compiled IJobChunk implementation that performs the chunk-by-chunk processing described in the summary. See "Methods" and nested-type details below.

  • private struct TypeHandle (nested)
    Generated helper struct that stores the EntityTypeHandle, ComponentTypeHandles and Buffer/Component lookups used by the job, and an __AssignHandles method to bind them to the system state.

Properties

  • (none publicly exposed)
    This system does not expose public properties. It uses internal/private fields and the ECS job pipeline to operate.

Constructors

  • public LaneObjectSystem()
    Default constructor. System creation is managed by DOTS/ECS and the Game world; initialization occurs in OnCreate.

Methods

  • protected override void OnCreate()
    Initializes m_ObjectSearchSystem (gets/creates Game.Objects.SearchSystem) and builds the EntityQuery that matches entities with any lane-related components. Calls RequireForUpdate(m_Query) so the system only runs when matching entities exist.

  • protected override void OnUpdate()
    Builds and schedules the Burst IJobChunk (LaneObjectJob) using the TypeHandle-based component & buffer handles and the moving search tree from m_ObjectSearchSystem.GetMovingSearchTree(...). Combines job dependencies, registers the job as a writer to the moving search tree (m_ObjectSearchSystem.AddMovingSearchTreeWriter(jobHandle)), and assigns base.Dependency to the scheduled job's JobHandle.

  • protected override void OnCreateForCompiler()
    Compiler-time helper used to bind type handles and assign queries when ECS generates code for the system. Calls __AssignQueries and __TypeHandle.__AssignHandles(ref base.CheckedStateRef).

  • private void __AssignQueries(ref SystemState state)
    Internal helper (generated) that ensures queries are assigned/created for the compiler; used by OnCreateForCompiler.

Nested: LaneObjectJob (Burst IJobChunk) - Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
For each chunk it: - Retrieves native arrays / buffers for the various lane-related components, Transform and PrefabRef. - For each entity type (cars, trailers, parked cars, watercraft, aircraft, trains, humans, animals, blocked-lane buffer): - If a lane buffer exists for the entity's lane, add an entry to that lane buffer via NetUtils.AddLaneObject (position varies: curve position, next position, front/rear pos for trains/parked trains, etc). - Otherwise compute object bounds using Transform + PrefabRef -> ObjectGeometryData -> ObjectUtils.CalculateBounds, and insert the entity into the moving search tree (m_SearchTree.Add(entity, new QuadTreeBoundsXZ(bounds))). - Trains and parked trains use TrainNavigationHelpers.GetCurvePositions to get front/rear curve positions and then add to the appropriate lane buffers if present. - Blocked lanes are processed by iterating the BlockedLane buffer and adding entries to the corresponding lane buffers if available. - The job uses: - ComponentTypeHandle (read-only) for current-lane components, Transform, PrefabRef, etc. - BufferTypeHandle to access per-entity blocked-lane buffers. - BufferLookup for writing to lane buffers. - ComponentLookup to resolve prefab geometry. - NativeQuadTree for spatial indexing of objects that are not attached to lane buffers.

Notes about thread-safety & performance: - The job is Burst-compiled and runs as an IJobChunk for parallel chunkized execution. - m_SearchTree is obtained from SearchSystem with readOnly:false and an out JobHandle dependency; the system registers the scheduled job as a writer so tree updates are safe. - NetUtils.AddLaneObject writes to per-lane DynamicBuffers via BufferLookup; these buffer lookups are safe to use from jobs when acquired correctly. - Geometry calculations are done on the main thread's stored geometry data via ComponentLookup (read-only).

Usage Example

You do not normally call this system directly — it runs automatically when the EntityQuery matches. Example snippets that are useful for modders:

  • Get the system instance (from a mod context) and check that it exists:
var world = World.DefaultGameObjectInjectionWorld;
var laneObjectSystem = world.GetExistingSystemManaged<Game.Serialization.LaneObjectSystem>();
if (laneObjectSystem != null) {
    // system is present and will run each frame when there are matching entities
}
  • Read lane objects for a specific lane entity (example: inspect the LaneObject buffer contents):
var em = World.DefaultGameObjectInjectionWorld.EntityManager;
Entity laneEntity = /* obtain lane entity */;
if (em.HasBuffer<Net.LaneObject>(laneEntity)) {
    var buffer = em.GetBuffer<Net.LaneObject>(laneEntity);
    for (int i = 0; i < buffer.Length; i++) {
        var laneObj = buffer[i];
        // laneObj contains entity reference and curve position stored by NetUtils.AddLaneObject
    }
}
  • Notes for modders:
  • If you add custom moving objects or customize Prefab/ObjectGeometryData, the system will either add them to lane buffers (if lanes are assigned) or to the moving search tree for spatial queries.
  • Avoid mutating lane buffers or the moving search tree outside the system's job while it runs — instead use ECS patterns (commands, separate systems) to safely modify data.
  • The job is Burst-compiled; keep user-managed managed calls out of components processed by this job.

If you want more concrete examples (e.g., how to add a custom entity with a CarCurrentLane so it appears in per-lane buffers, or how to query the moving search tree), tell me which scenario you need and I can add a short code sample.