Game.SecondaryObjectSystem
Assembly: Assembly-CSharp (game code)
Namespace: Game.Objects
Type: class
Base: GameSystemBase
Summary:
SecondaryObjectSystem is a game system responsible for spawning, updating and removing secondary objects tied to network elements and areas (nodes/edges/areas). Secondary objects include street lights, traffic signs, utility objects/nodes, track-end objects, placeable objects and spawnable placeholders. The system uses several highly parallel Burst-compiled jobs to collect owners, evaluate placement rules and requirements, match spawnable placeholders, and create or reuse entity instances using an EntityCommandBuffer. It also updates anchors for utility lanes and handles temporary/replace state, elevation, lighting flags and pseudo-random seeds for deterministic appearance.
Fields
-
private ToolSystem m_ToolSystem
Holds a reference to the ToolSystem (used to query editor mode and related tool state). -
private CityConfigurationSystem m_CityConfigurationSystem
Reference to CityConfigurationSystem used for settings such as left-hand traffic and default theme. -
private ModificationBarrier4B m_ModificationBarrier
Command buffer barrier used to queue structural changes (entity create/remove/set) performed by jobs. -
private EntityQuery m_ObjectQuery
EntityQuery used to find owners that have SubObject buffers and require updates (Updated or Deleted). -
private EntityQuery m_LaneQuery
EntityQuery used to find utility lanes that act as anchors (Updated + Owner + UtilityLane). -
private ComponentTypeSet m_AppliedTypes
ComponentTypeSet containing the components applied during owner -> subobject processing (Applied, Created, Updated). -
private ComponentTypeSet m_SecondaryOwnerTypes
ComponentTypeSet used when creating a new secondary object archetype (Secondary + Owner). -
private ComponentTypeSet m_TempAnimationTypes
ComponentTypeSet for temporary objects that require animation/interpolation components (Temp + Animation + InterpolatedTransform). -
private TypeHandle __TypeHandle
Internal aggregated handles for many component lookups/type handles used by the system's jobs.
Properties
- None (this system exposes no public properties)
Constructors
public SecondaryObjectSystem()
Creates the system instance. Most initialization is done in OnCreate; the constructor is preserved for runtime.
Methods
-
protected override void OnCreate()
: System.Void
Initializes system references (ToolSystem, CityConfigurationSystem, ModificationBarrier4B) and sets up EntityQueries and ComponentTypeSets used by the jobs. -
protected override void OnUpdate()
: System.Void
Main update entry. Checks if there are objects or lanes to process and schedules the pipeline of jobs to update secondary objects and lane anchors. Allocates a temporary NativeQueue (UpdateData) which is filled by jobs and disposed after dependencies are resolved. -
protected override void OnCreateForCompiler()
: System.Void
Internal helper used to assign queries and type handles for the compiler path. (Called by the generated code path.) -
private void UpdateLanes(NativeQueue<UpdateData> updateQueue)
: System.Void
Schedules SecondaryLaneAnchorJob to update utility-lane anchors and writes anchor transforms into the updateQueue via FillUpdateMapJob. Uses a NativeParallelMultiHashMap to map owners to anchor data. -
private void UpdateObjects(NativeQueue<UpdateData> updateQueue)
: System.Void
Schedules a pipeline that: - collects owners that have subobjects (CheckSubObjectOwnersJob),
- merges owner lists (CollectSubObjectOwnersJob),
-
processes each owner to create/reuse secondary objects and evaluate placeholders (UpdateSubObjectsJob). Uses ModificationBarrier4B's EntityCommandBuffer to perform structural changes.
-
private void __AssignQueries(ref SystemState state)
: System.Void
Internal helper used to assign any EntityQueryBuilder logic (kept minimal here). -
Numerous nested job types and helper methods used inside UpdateSubObjectsJob:
- FillUpdateMapJob : IJob — drains update queue into a NativeParallelMultiHashMap.
- SecondaryLaneAnchorJob : IJobChunk — adjusts Curve anchors for utility lanes, finds anchor positions by inspecting subobjects and updated transforms.
- CheckSubObjectOwnersJob : IJobChunk — enqueues owners requiring a secondary object update; handles deleted owners.
- CollectSubObjectOwnersJob : IJob — collects and merges owner entries from a queue into a deduplicated list.
- UpdateSubObjectsJob : IJobParallelForDefer — main heavy-lifting job. For each owner it:
- gathers old/original secondary entities,
- evaluates net composition objects, streetlights, traffic signs, utility nodes, track lane end/start objects,
- selects spawnable objects for placeholders considering requirements, probabilities and random seeds,
- either reuses an existing entity (clears Deleted, updates components) or creates a new object entity using the prefab's archetype and sets components (Owner, PrefabRef, Transform, Temp, StreetLight, TrafficLight, Tree, Elevation, LocalTransformCache, PseudoRandomSeed, Native, etc.),
- handles alignment (AnchorTop/Center/Ground), lowered flags, and elevation corrections,
- updates Road flags (IsLit/AlwaysLit) via m_RoadData when street lights are present. The job contains many helper methods:
- FillOldSubObjectsBuffer / FillOriginalSubObjectsBuffer
- RemoveUnusedOldSubObjects
- CreateSecondaryNodeObjects / CreateSecondaryEdgeObjects / CreateSecondaryAreaObjects
- CheckRequirements (placeholder requirements)
- CreateSecondaryObject (multiple overloads) — core logic that either finds an existing secondary entity or instantiates a new one, configures components & animation/seed/state.
- GetClosestCarLane, AddNodeLanes, AddEdgeLanes, FindOldSecondaryObject, FindOriginalSecondaryObject, Remap/LerpRemap helpers for bezier blending
Notes on behavior: - The system is heavily optimized for multi-threaded execution using Unity's DOTS patterns, Burst, Native containers and ComponentLookups. Many temporary Native containers are allocated with Allocator.Temp and disposed within job execution. - Randomization is carefully handled via pseudo-random seeds saved as components to ensure deterministic re-creation of objects. - Placeholder groups and spawnable object selection respect per-owner constraints and object requirements (placeholder-required themes or other placeholder objects).
Usage Example
// Typical mod code to access the system instance from the World and (optionally) force a run:
var world = World.DefaultGameObjectInjectionWorld;
var secondarySystem = world.GetOrCreateSystemManaged<Game.Objects.SecondaryObjectSystem>();
// The system runs automatically in the ECS update loop. If you must trigger changes manually,
// modify owners/SubObject buffers and mark them Updated/Deleted — the system will pick them up
// on the next frame update. Example (pseudocode):
// ownerEntity.GetBuffer<SubObject>().Add(new SubObject { m_SubObject = prefabEntity });
// ownerEntity.AddComponent<Updated>();
If you want, I can also extract and document specific nested jobs (UpdateSubObjectsJob helpers, traffic sign selection, streetlight placement) into their own reference sections with parameters and behavior notes.