Game.Objects.OverrideSystem
Assembly:
Assembly-CSharp (Unity game assembly for Cities: Skylines 2 mods)
Namespace:
Game.Objects
Type:
class
Base:
GameSystemBase
Summary:
OverrideSystem is a game ECS system responsible for detecting and resolving object collisions that cause objects to be "overridden" (i.e., temporarily suppressed by higher-priority geometry or other objects/nets/areas). It collects objects whose bounds were updated (from object updates, net updates, or area/lots updates), performs spatial queries against object/net/area quadtrees using Burst-compiled jobs, and updates object state components (Updated/Overridden) and the static object search tree accordingly via a ModificationBarrier command buffer. The system is heavily multi-threaded (Jobs + Burst), uses Native collections and quadtrees, and coordinates work across several nested job structs (FindUpdatedObjectsJob, CheckObjectOverrideJob, UpdateObjectOverrideJob, CollectObjectsJob) to ensure correct ordering and efficient collision checking.
This system is useful for modders who need to understand how the game determines when placed objects are considered overridden (e.g., by roads, areas, other objects) and how to safely interact with those component states or the search trees.
Fields
-
private UpdateCollectSystem m_ObjectUpdateCollectSystem
This holds a reference to the system that collects updated object bounds (object updates). Used to read which objects need re-checking. -
private Game.Net.UpdateCollectSystem m_NetUpdateCollectSystem
Reference to the net update-collector system (roads/edges), used to gather updated net bounds. -
private Game.Areas.UpdateCollectSystem m_AreaUpdateCollectSystem
Reference to the area/lots update collector (lots/areas). -
private SearchSystem m_ObjectSearchSystem
Reference to the object search system (static object quadtree) used for spatial queries and read/write access to the static object search tree. -
private Game.Net.SearchSystem m_NetSearchSystem
Reference to the net search system (net quadtrees) for spatial queries against nets. -
private Game.Areas.SearchSystem m_AreaSearchSystem
Reference to the area search system (area quadtrees) for spatial queries against areas. -
private ModificationBarrier5 m_ModificationBarrier
Barrier used to create command buffers for safe structural changes (add/remove components) from jobs. -
private ToolSystem m_ToolSystem
Used to determine editor mode (actionMode.IsEditor()) and other tool-related state impacting collision logic. -
private ComponentTypeSet m_OverriddenUpdatedSet
A ComponentTypeSet prebuilt for adding/removing Overridden and Updated components together through command buffers. -
private TypeHandle __TypeHandle
Internal TypeHandle containing ComponentLookup/BufferLookup handles used by job structs. Populated via __AssignHandles in OnCreateForCompiler.
Properties
- None (this system exposes no public properties).
Constructors
public OverrideSystem()
Default constructor. System created by the ECS world. No user-side initialization required.
Methods
-
protected override void OnCreate()
Initializes references to dependent systems (object/net/area UpdateCollect systems and SearchSystems), retrieves the ModificationBarrier and ToolSystem, and constructs the m_OverriddenUpdatedSet. Called once when the system is created. -
protected override void OnUpdate()
Main update method. If any of the update-collector systems report updates (objects, nets, lots), it: - Builds a deferred NativeList and NativeHashSet to collect objects to check.
- Calls CollectUpdatedObjects(...) (schedules FindUpdatedObjectsJob per updated bounds and then CollectObjectsJob).
- Schedules CheckObjectOverrideJob (parallel for deferred) to perform collision detection for each candidate object (it uses multiple quadtrees: object, net, area).
- Schedules UpdateObjectOverrideJob to process tree actions and overridable resolution results, applying component changes via the ModificationBarrier command buffer and updating the static object search tree masks.
- Adds search-tree writer/reader job handles to the corresponding search systems and registers the modification barrier job as the producer.
This method coordinates job dependencies, disposes native containers with correct dependency chaining, and updates base.Dependency with the final job handle.
private JobHandle CollectUpdatedObjects(NativeList<Entity> updateObjectsList, NativeHashSet<Entity> objectSet)
Schedules jobs to find objects whose bounds intersect updated bounds from the three update collectors. Uses:- FindUpdatedObjectsJob to iterate the object search tree and enqueue objects in three NativeQueues.
-
CollectObjectsJob to merge these queues into updateObjectsList and a deduplicating objectSet. Returns a JobHandle representing completion of the collection stage. Also registers readers with object search system.
-
protected override void OnCreateForCompiler()
Called by generated code paths / compiler pipeline. Assigns queries and component lookup handles through __AssignQueries and __TypeHandle.__AssignHandles for job usage. -
private void __AssignQueries(ref SystemState state)
Internal helper used at compiler-time to assign/validate entity queries. (Minimal in this implementation, creates and disposes a temporary EntityQueryBuilder.) -
private void __AssignHandles(ref SystemState state)
(via TypeHandle.__AssignHandles)
Populates the TypeHandle lookups for many ComponentLookupand BufferLookup fields used inside jobs — called from OnCreateForCompiler. -
public OverrideSystem()
(See Constructors above) default public constructor.
Notes on nested job/struct types (high-level): - TreeAction (struct): small data used to update the quadtree mask for a single entity. - OverridableAction (struct, IComparable): used to sort and resolve overridable collisions between objects. Contains entity, other entity, mask, priority and whether the other was overridden. - UpdateObjectOverrideJob (Burst, IJob): Consumes TreeAction and OverridableAction queues, applies updates to the static object search-tree masks, and uses a command buffer to add/remove Overridden/Updated components. It performs the final resolution of overridable collisions (sorting & marking). - FindUpdatedObjectsJob (Burst, IJobParallelForDefer): Iterates a quadtree for each changed bounds to enqueue object entities into a queue. - CollectObjectsJob (Burst, IJob): De-duplicates entities from multiple queues into a single NativeList / NativeHashSet. - CheckObjectOverrideJob (Burst, IJobParallelForDefer): Main collision-check job. For each candidate object it: - Validates the object prefab & geometry flags (Overridable / DeleteOverridden). - Builds Bounds and CollisionMask for the object. - Uses three iterator types to query object, net, and area quadtrees (and the connected edges/nodes when needed): - ObjectIterator: iterates other objects and checks detailed geometry collisions (legs, circular vs box bounds, etc.), accounting for owner chains, attachments, subobjects, and whether collisions are overridable. - NetIterator: iterates nets/edges and performs net-vs-object intersection tests (uses Game.Net ValidationHelpers). - AreaIterator: iterates areas/triangles to check area overrides. - Collects overridable collisions into a NativeList and uses them to enqueue OverridableAction items for delayed resolution. - If collision status differs from existing Overridden component, it issues command-buffered component adds/removes and enqueues TreeAction to update search-tree masks.
Important implementation details: - Uses Burst and Jobs to parallelize collision checks and iteration across quadtrees. - Uses NativeQuadTree iterators (INativeQuadTreeIterator) and both read-only and writable access to the static object search tree. - Carefully manages dependencies between search-tree readers/writers and modification barrier to avoid race conditions. - Uses ComponentLookup/BufferLookup to read ECS components in jobs (populated via TypeHandle). - Many GC-free native allocations are used (NativeList, NativeQueue, NativeHashSet) and disposed with JobHandle chaining.
Usage Example
// This system is managed by the ECS world. Typical internal usage (inside the system) is:
//
// In OnCreate the system retrieves required systems and prepares ComponentTypeSet:
protected override void OnCreate()
{
base.OnCreate();
m_ObjectUpdateCollectSystem = World.GetOrCreateSystemManaged<UpdateCollectSystem>();
m_NetUpdateCollectSystem = World.GetOrCreateSystemManaged<Game.Net.UpdateCollectSystem>();
m_AreaUpdateCollectSystem = World.GetOrCreateSystemManaged<Game.Areas.UpdateCollectSystem>();
m_ObjectSearchSystem = World.GetOrCreateSystemManaged<SearchSystem>();
m_NetSearchSystem = World.GetOrCreateSystemManaged<Game.Net.SearchSystem>();
m_AreaSearchSystem = World.GetOrCreateSystemManaged<Game.Areas.SearchSystem>();
m_ModificationBarrier = World.GetOrCreateSystemManaged<ModificationBarrier5>();
m_ToolSystem = World.GetOrCreateSystemManaged<ToolSystem>();
m_OverriddenUpdatedSet = new ComponentTypeSet(ComponentType.ReadWrite<Overridden>(), ComponentType.ReadWrite<Updated>());
}
// If you need to access the OverrideSystem from a mod:
// (obtain the system from the World to inspect or invoke behavior)
var overrideSystem = World.GetExistingSystemManaged<Game.Objects.OverrideSystem>();
// You can read system state or observe its effects by querying components:
// e.g. find entities with Overridden component, inspect Updated, etc.
Notes for modders: - Avoid directly modifying the static object search tree from your own jobs without coordinating with the corresponding SearchSystem writer handles — use AddStaticSearchTreeWriter / AddStaticSearchTreeReader or follow the search system's API to register dependencies. - If you schedule jobs that read any of the same component types or search trees, you must honor and combine job dependencies returned by the system (look at how this system combines dependencies and registers readers/writers). - The system performs low-level geometry checks and uses precise flags (GeometryFlags, CollisionMask). When creating custom object prefabs or customizing geometry, ensure flags and geometry data are properly set so override logic behaves correctly. - Use the ModificationBarrier to apply structural changes safely from jobs.