Skip to content

Game.Net.LaneSystem

Assembly: Assembly-CSharp
Namespace: Game.Net

Type: class

Base: GameSystemBase

Summary:
LaneSystem is the core system responsible for generating, updating and removing lane entities for network (net) objects in Cities: Skylines 2. It inspects edges, nodes and object sublanes, matches them against net composition data and prefab lane definitions and creates the appropriate lane entities (edge lanes, node lanes, pedestrian lanes, utility lanes, track lanes, parking lanes, etc). The heavy-lifting is done in a Burst-compiled IJobChunk (UpdateLanesJob) that runs in parallel and emits entity commands via a modification barrier. The system handles: - Creating and reusing lane entities based on a LaneKey (lane geometry + prefab + master/slave flags). - Creating edge-to-edge and node-to-node connections (car/track/pedestrian/utility). - Special handling for roundabouts, crosswalks, orphan lanes, anchors and auxiliary lanes. - Temporary (editor) lanes, replacements and prefab spawnable selection. - Terrain sampling, elevation adjustments and cut ranges for pedestrian crosswalks. - Using multiple helper systems: CityConfigurationSystem, ToolSystem, LaneReferencesSystem, TerrainSystem, ModificationBarrier4.

This system is central to net generation and should be treated as internal; mod code should avoid directly changing its private state. Instead use public APIs or systems exposed by the game (or use the same command buffer approach via a modification barrier) when possible.


Fields

  • private CityConfigurationSystem m_CityConfigurationSystem
    Holds a reference to the CityConfigurationSystem (provides global city settings such as leftHandTraffic and default theme).

  • private ToolSystem m_ToolSystem
    Reference to the ToolSystem used to detect editor mode and other tool-related state.

  • private LaneReferencesSystem m_LaneReferencesSystem
    Used to obtain and write lane reference data (for example the skip-lane queue writer).

  • private TerrainSystem m_TerrainSystem
    Provides terrain height data used for terrain sampling when creating object lanes and utilities.

  • private ModificationBarrier4 m_ModificationBarrier
    Barrier used to create an EntityCommandBuffer. All entity creation/removal/updates are done through the command buffer returned by this barrier.

  • private EntityQuery m_OwnerQuery
    EntityQuery used to select owners (entities that contain SubLane buffers) that require lane updates (Updated/Deleted/other conditions used by the system).

  • private EntityQuery m_BuildingSettingsQuery
    Used to read building configuration data (e.g. to add construction border sublanes for buildings).

  • private ComponentTypeSet m_AppliedTypes
    Prebuilt ComponentTypeSet representing components that mark lanes as applied (Applied/Created/Updated). Used when toggling between temporary/applied lanes.

  • private ComponentTypeSet m_DeletedTempTypes
    ComponentTypeSet used to identify temporary lanes to delete.

  • private ComponentTypeSet m_TempOwnerTypes
    ComponentTypeSet for temporary owner attributes.

  • private ComponentTypeSet m_HideLaneTypes
    ComponentTypeSet used for hiding lane rendering components (CullingInfo / MeshBatch / MeshColor).

  • private TypeHandle __TypeHandle
    Internal aggregated type handles used by the Burst IJobChunk (UpdateLanesJob). This bundles EntityTypeHandle, ComponentTypeHandles and BufferTypeHandles required for chunk processing.

(There are many more locally-used temporary structs, nested types and job-local collections inside UpdateLanesJob—see Methods for the job summary.)

Properties

  • (none public)
    This system does not expose public properties. Interaction happens through the ECS world and other public game systems / command buffers.

Constructors

  • public LaneSystem()
    Default constructor. System initialization is done by the framework and OnCreate. The constructor itself simply calls the base constructor (as generated/preserved by the game).

Methods

  • protected override void OnCreate()
    Initializes references to other systems (CityConfigurationSystem, ToolSystem, LaneReferencesSystem, TerrainSystem, ModificationBarrier4), builds entity queries, prepares ComponentTypeSets used later, and calls RequireForUpdate(m_OwnerQuery) to run only when relevant owners exist.

  • protected override void OnUpdate()
    Schedules the Burst-compiled UpdateLanesJob as a parallel IJobChunk. It:

  • Assigns many ComponentTypeHandles, ComponentLookup/BufferLookup and other data into the job.
  • Configures job inputs (left-hand traffic, editor mode, random seed, terrain height data, building config).
  • Schedules it with m_OwnerQuery and attaches the resulting JobHandle to the modification barrier, terrain system and lane references system as needed.
  • Because the heavy work is inside the job, OnUpdate mainly sets up and schedules the job.

  • protected override void OnCreateForCompiler()
    Compiler helper used by the game to wire up query/type handles at compile time. (Internal use.)

  • UpdateLanesJob (private nested BurstCompile struct) : IJobChunk
    Primary job that does the lane generation and update per chunk. Key responsibilities:

  • For each owner chunk (edge, node or object), determine whether to delete lanes or update them.
  • Build lists of ConnectPosition entries (source/target), filter them and create lanes for:
    • Edge lanes (CreateEdgeLane, CreateEdgeLanes, CreateEdgeConnectionLane).
    • Node lanes and connections (CreateNodeLane, CreateNodeCarLanes, CreateNodeTrackLanes, CreateNodePedestrianLane, CreateNodeUtilityLane).
    • Roundabout lane creation (GetRoundaboutLaneCount, CreateRoundaboutCarLanes).
    • Orphan lanes (CreateOrphanLanes).
    • Object sub-lanes (CreateObjectLane).
    • Utility connection pairing and special underground/ground handling (GetConnectionLanePrefab, CalculateUtilityConnectPosition).
  • Tries to reuse old lanes (FillOldLaneBuffer / RemoveUnusedOldLanes) by matching LaneKey (Lane geometry + prefab + flags) to existing lane entities.
  • Emits entity commands to create, set or delete components using an EntityCommandBuffer.ParallelWriter.

(The job contains dozens of helper functions used above. The most relevant ones a modder may want to understand are listed below.)

  • Key helper methods inside UpdateLanesJob (summaries):
  • FillOldLaneBuffer(...)
    Collects existing lanes for an owner (edge/node/object) into a NativeHashMap keyed by LaneKey so they can be reused instead of created anew.
  • RemoveUnusedOldLanes(...)
    Removes and marks as Deleted any old lanes not reused during this update.
  • UpdateLanes(int jobIndex, NativeList laneBuffer)
    Removes the Deleted component and adds Updated to lanes that were re-used or updated.
  • CreateEdgeLanes(...) / CreateEdgeLane(...)
    Create the lane entities along an edge (edge lanes), handle anchors and auxiliary lanes.
  • CreateEdgeConnectionLanes(...) / CreateEdgeConnectionLane(...) / CreateCarEdgeConnections(...)
    Create side-connection lanes from nodes to edges (car/pedestrian/utility).
  • GetNodeConnectPositions(...) / GetNodeConnectPositions(entity, edge, isEnd, ...)
    Extracts connectable positions (ConnectPosition) for a node from composition lanes and sublanes, including elevation, tangents and group indices.
  • ProcessCarConnectPositions(...) / CreateNodeCarLanes(...)
    Main algorithm that takes source and target connect positions at a node and determines which car lanes to spawn between them (handles turns, yield/priority, forbidden/unsafe flags).
  • CreateNodeLane(...)
    Creates or reuses a single node lane entity for a connection between two ConnectPositions (handles car, track, utility and pedestrian variants).
  • CreateNodeTrackLanes(...), CreateNodePedestrianLanes(...), CreateNodeUtilityLanes(...)
    Specialized lane creation for rail, pedestrian and utility lanes respectively.
  • GetRoundaboutLaneCount(...) / CreateRoundaboutCarLanes(...)
    Specialized logic for roundabout lane generation and lane grouping.
  • CreateObjectLane(...)
    Create lanes associated with buildings/objects (sub-lanes), sample terrain, and respect clear areas.
  • CheckPrefab(...)
    Used to pick spawnable object prefabs (placeholder/spawnable logic) and manage randomization groups in non-editor mode.
  • ModifyCurveHeight(...)
    Adjusts interior control points of Bezier curves to respect composition surface heights, roundabouts and level crossings.

  • Other private helpers and small utilities (listed in code): FindAnchors, IsAnchored, FindAnchor, PresetCurve, ExtractNextConnectPosition, GetMiddleConnections, GetMiddleConnectionCurves, Filter* (FilterNodeConnectPositions, FilterMainCarConnectPositions, FilterActualCarConnectPositions, FilterTrackConnectPositions, FilterPedestrianConnectPositions, FilterUtilityConnectPositions), CalculateYieldOffset, IsTurn, CanConnectTrack, GetGroundPosition, GetConnectionLanePrefab, GetCompositionData, FindBestConnectionLane, FindClosestLane, CalculateAuxialryZOffset, CalculateUtilityConnectPosition, ReplaceTempOwner, GetOriginalLane, and many small data-structure types (LaneKey, ConnectionKey, ConnectPosition, MiddleConnection, EdgeTarget, LaneAnchor, LaneBuffer, CompositionData, etc.).

Notes about the job: - The job is heavy; it uses NativeLists, NativeHashMaps, NativeParallelHashSets, and many temporary buffers. It is Burst-compiled and runs in parallel across owner chunks. - Because of entity command buffer usage, created/removed components are applied through the ModificationBarrier4 command buffer.

Usage Example

This system is internal and normally scheduled automatically by the ECS world. As a modder you typically don't call its internals directly, but you can get a reference to the system (read-only) or use the modification barrier to issue changes that will be picked up on the next update.

// Get the system (World assumed to be the default injection world)
var world = Unity.Entities.World.DefaultGameObjectInjectionWorld;
var laneSystem = world.GetOrCreateSystemManaged<Game.Net.LaneSystem>();

// Note: LaneSystem schedules UpdateLanesJob automatically via OnUpdate.
// To force a full world update you can let the world progress or (in editor/testing) call:
world.Update(); // runs system updates including LaneSystem

// For adding/removing lane-related entities safely use the modification barrier
var modificationBarrier = world.GetExistingSystemManaged<Game.Net.ModificationBarrier4>();
var ecb = modificationBarrier.CreateCommandBuffer();
// Example: create a simple entity that would later be seen by LaneSystem processing
var archetype = world.EntityManager.CreateArchetype(typeof(Game.Prefabs.PrefabRef), /* ... */);
var e = ecb.CreateEntity(archetype);
ecb.SetComponent(e, new Game.Prefabs.PrefabRef { m_Prefab = somePrefabEntity });
// Commit by scheduling world update; LaneSystem will pick up changes in next run.

Additional notes for modders: - LaneSystem is highly internal and optimized for performance. Avoid modifying internal data structures directly. - If you need to influence lane creation (for example for a custom net prefab), best approach is to provide appropriate NetComposition / NetLane / composition pieces in prefab data so the system can generate lanes naturally. - For temporary (editor) lane creation or replacement of owners, the system handles Temp component semantics; use the provided editor APIs rather than directly mutating internal lanes. - If you need to run custom logic after lanes are created, you can register to run after the ModificationBarrier4 (or read Updated components) so that your system sees stable lane entities. - Be careful with Burst-incompatible types and job-safety rules when interfacing with this system — the job uses many NativeContainers and parallel writers.


If you want, I can: - Extract and document a specific nested struct/enum (e.g., ConnectPosition, LaneKey, or the UpdateLanesJob API) in more detail. - Produce a quick diagram or step-by-step flow of how a node/edge is processed into lanes. - Provide safe patterns to hook into lane creation for mods (recommended approach using command buffers / the modification barrier).