Game.Tools.GenerateEdgesSystem
Assembly: Game (Assembly-CSharp)
Namespace: Game.Tools
Type: class
Base: GameSystemBase
Summary:
GenerateEdgesSystem is an ECS system responsible for converting high-level creation definitions (CreationDefinition + NetCourse) into concrete network edges (Edge entities) in the world. It collects nodes and local connect points, reuses or creates edge entities, handles splitting/duplicating of existing edges, applies geometry/elevation adjustments, sets up connected nodes, manages build order indices, and schedules the work using several Burst-compiled jobs. The system coordinates with TerrainSystem, WaterSystem, GenerateObjectsSystem and a ModificationBarrier (m_TempEdgesBarrier) to safely write entity changes from jobs.
Fields
-
private TerrainSystem m_TerrainSystem
Holds a reference to the TerrainSystem used to read terrain height data for edge placement and adjustment. -
private WaterSystem m_WaterSystem
Reference to the WaterSystem used to read water surface data (used for on-water geometry adjustments). -
private GenerateObjectsSystem m_GenerateObjectsSystem
Reference used to get reused owner mapping and other object-generation helpers. -
private ToolSystem m_ToolSystem
Reference used to detect editor/action mode (editor vs runtime behavior). -
private ModificationBarrier2 m_TempEdgesBarrier
A barrier used to create a parallel command buffer for safely creating/updating temporary edge entities from jobs. -
private NativeValue<uint> m_BuildOrder
NativeValue used to store and increment a build-order counter for newly created edges; persisted across the system lifecycle. -
private EntityQuery m_CreatedEdgesQuery
Query that matches newly created edge entities (Created + Edge + BuildOrder, excluding Temp) — used to update/track build order. -
private EntityQuery m_DefinitionQuery
Query for creation definitions to process (CreationDefinition + NetCourse + Updated and additional constraints). Primary driver for GenerateEdges job pipeline. -
private EntityQuery m_DeletedQuery
Query for deleted edges (Edge + Deleted + Temp + PrefabRef) used when building the old-edge map. -
private TypeHandle __TypeHandle
Internal generated holder for component/entity type handles used for scheduling jobs (populated in OnCreateForCompiler).
Properties
- (none)
Notes: The system exposes GetBuildOrder() as a method returning the NativeValue
Constructors
public GenerateEdgesSystem()
Default constructor. The system initializes references and native state in OnCreate; the constructor itself is empty/standard for ECS systems.
Methods
protected override void OnCreate()
Initializes native resources and acquires references to other systems:- Allocates the persistent NativeValue
m_BuildOrder. - Fetches TerrainSystem, WaterSystem, GenerateObjectsSystem, ToolSystem, and ModificationBarrier2 from the World.
- Creates and configures EntityQueries (m_CreatedEdgesQuery, m_DefinitionQuery, m_DeletedQuery).
-
Calls RequireAnyForUpdate to avoid running unless there are relevant changes. Important: This method registers the system dependencies and persistent native allocations.
-
protected override void OnDestroy()
Disposes of persistent resources (m_BuildOrder.Dispose()) and performs base cleanup. Ensures no native leak of the persistent build order. -
public NativeValue<uint> GetBuildOrder()
Returns the internal NativeValuethat holds the build-order counter. Modders can read/modify (careful: this is a native type and must be used from correct thread/context) to influence build ordering. -
protected override void OnUpdate()
Main runtime method. If there are CreationDefinition/NetCourse updates (m_DefinitionQuery) it builds and schedules a pipeline of Burst jobs: - Creates temporary collections: nodeMap, localConnectQueue/list, oldEdgeMap, reusedOwnerMap.
- Schedules jobs: CheckNodesJob (collects nodes & local connects), FillOldEdgesJob (maps old edges), CheckDefinitionsJob, CollectLocalConnectItemsJob, and GenerateEdgesJob which performs most of the creation/splitting/duplication logic and writes to entities through m_TempEdgesBarrier's command buffer.
- Adds readers to Terrain/Water/GenerateObjects systems and registers job handles with the modification barrier.
-
Also updates build-order via UpdateBuildOrderJob if created edges are found. This method coordinates job dependencies and disposes temporary native containers once their dependent jobs complete.
-
protected override void OnCreateForCompiler()
Internal helper called by the generated code path to assign queries and to populate __TypeHandle with component type/lookup handles. Used by the ECS code generator/IL2CPP compilation pathway. -
private void __AssignQueries(ref SystemState state)
Internal method used during OnCreateForCompiler to setup any extra queries (here it creates and disposes an EntityQueryBuilder — used by codegen). -
(Numerous nested job/struct types)
The system contains several Burst-compiled nested types (jobs) implementing the heavy-lifting logic. Brief summary of the main nested jobs and structs: -
NodeMapKey (struct)
- Key used for mapping nodes (permanent/editor/position/original entity) in a NativeParallelMultiHashMap.
-
LocalConnectItem (struct)
- Represents a potential connection candidate (position, radius, node entity, layers, height range, flags) collected from nodes for local edge-node connection checks.
-
OldEdgeKey (struct)
- Key used to look up existing (old) edges that can be reused when generating/updating edges.
-
CheckNodesJob : IJobChunk (Burst)
- Scans node archetypes (Node) and populates m_NodeMap and m_LocalConnectQueue for later processing. Determines if nodes are permanent or temp and enqueues LocalConnectItem entries.
-
FillOldEdgesJob : IJobChunk (Burst)
- Iterates existing Edge entities (and associated metadata) and builds m_OldEdgeMap (OldEdgeKey -> Entity) for reuse-checks when generating new edges.
-
CheckDefinitionsJob : IJobChunk (Burst)
- Inspects CreationDefinition chunks and adds NodeMapKey entries for definitions that reference existing original edge entities, enabling detection of definitions that should map to existing nodes.
-
CollectLocalConnectItemsJob : IJob (Burst)
- Simple consolidation job that dequeues m_LocalConnectQueue into a contiguous NativeList m_LocalConnectList for random access during edge generation.
-
GenerateEdgesJob : IJobChunk (Burst)
- Core job performing creation, duplication, splitting and updating of edges:
- For CreationDefinition entries: resolves start/end nodes (TryGetNode), checks for existing connections (ConnectionExists), computes Curve info (use straight edges vs cut from course), adjusts elevation/terrain, produces Temp flags, attempts to reuse old entities (TryGetOldEntity) or creates new edge entities, sets many components (Curve, PrefabRef, Elevation, Owner, Fixed, Upgraded, SubReplacement, Road, Condition, TramTrack, Native, ElectricityConnection, etc.), and computes connected nodes via FindNodeConnections.
- For Temp nodes/edges: may SplitEdge or DuplicateEdge when required based on node/temp flags and existing mappings.
- Uses m_NodeMap, m_LocalConnectList, m_OldEdgeMap, m_ReusedOwnerMap extensively.
- Writes commands through the EntityCommandBuffer.ParallelWriter provided by m_TempEdgesBarrier.
The job also contains helper methods: - UpdateNodeConnections, ShouldDuplicate, DuplicateEdge, TryGetNodes, SplitEdge, CreateTempEdge, TryGetNode, TryGetOldEntity, CheckRoadAlignment, SetRoadAlignment, ConnectionExists, FindNodeConnections.
Important: This job uses many ComponentLookup and BufferLookup handles and depends on terrain/water/build-order/prefab data.
-
UpdateBuildOrderJob : IJob (Burst)
- Scans newly created edge chunks to update the global m_BuildOrder counter to avoid build-order collisions.
Notes on memory and threading: - The system creates various temporary Native containers (NativeQueue, NativeList, NativeParallelMultiHashMap, NativeHashMap) with Allocator.TempJob and disposes them after scheduling dependent jobs. - Several jobs are Burst-compiled for performance and scheduled in parallel. All job handles are correctly joined and associated with the modification barrier to produce structural entity changes safely.
Usage Example
// Example: reading the BuildOrder counter from a mod or another system
public class MySystem : SystemBase
{
private GenerateEdgesSystem m_GenerateEdges;
protected override void OnCreate()
{
m_GenerateEdges = World.GetExistingSystemManaged<GenerateEdgesSystem>();
}
protected override void OnUpdate()
{
if (m_GenerateEdges != null)
{
// Get the NativeValue<uint> that stores build order.
NativeValue<uint> buildOrder = m_GenerateEdges.GetBuildOrder();
// Read current value (safe on main thread)
uint current = buildOrder.value;
// Example: reserve 16 build order IDs (careful: must consider thread-safety)
buildOrder.value = current + 16;
}
}
}
Additional notes for modders: - GenerateEdgesSystem is tightly coupled to the game's ECS component set (Edge, Node, CreationDefinition, NetCourse, PrefabRef, NetData, NetGeometryData, etc.). When creating or modifying components that influence network generation, ensure compatibility with its expectations (layer flags, geometry flags, LocalConnectData, etc.). - When interacting with native containers returned by GetBuildOrder or other native handles, respect thread-safety and lifetime (NativeValue is persistent and must not be disposed by callers). - This system performs structural changes to entities via a ModificationBarrier (m_TempEdgesBarrier). If your mod needs to create/update edges in the same frame, coordinate with or run after this system to avoid race conditions. - Many nested jobs are Burst-compiled—if you modify them, ensure Burst/Burst-compatible constructs are used (no managed references captured by jobs).