Game.Net.CarLane
Assembly: Game (Cities: Skylines 2)
Namespace: Game.Net
Type: struct
Base: IComponentData, IQueryTypeParameter, ISerializable
Summary:
Represents per-lane data for vehicle (car) traffic in the game's ECS. Stores access restriction (entity reference), lane flags, speed limits (default and current), curvature, grouping, blockage/caution ranges encoded as bytes, a flow offset used in pathfinding/flow calculations, and other small lane-specific metadata. The struct provides binary serialization/deserialization with compatibility handling for different saved-game/engine versions.
Fields
-
public Entity m_AccessRestriction
Reference to an Entity that defines access restrictions for this lane (e.g., vehicle type access modifiers). This value is only read from serialized data when the saving/loading context version is >= Version.pathfindAccessRestriction. -
public CarLaneFlags m_Flags
Bitflags describing lane properties (e.g., whether the lane is unsafe, a side connection, etc.). During deserialization compatibility fixes are applied depending on save file version (see Deserialize notes). -
public float m_DefaultSpeedLimit
Default speed limit for the lane. Always read from serialized data. -
public float m_SpeedLimit
Current (possibly modified) speed limit. If loading from an older version that does not contain a modified speed limit, this is set to m_DefaultSpeedLimit. -
public float m_Curviness
Curviness value for the lane (used for lane geometry/path smoothing/pathfinding). -
public ushort m_CarriagewayGroup
Group id for carriageways. Used to group lanes into carriageways for certain traffic logic. -
public byte m_BlockageStart
Encoded byte (0..255) representing start position of a blockage along the lane. When interpreted as a normalized value it is multiplied by 1/255 (≈0.003921569f) to form a float position in bounds. -
public byte m_BlockageEnd
Encoded byte representing end position of a blockage along the lane. -
public byte m_CautionStart
Encoded byte representing start position of a caution range along the lane (used since Version.trafficImprovements). -
public byte m_CautionEnd
Encoded byte representing end position of a caution range. -
public byte m_FlowOffset
Small integer offset used for pathfinding/flow calculations. Present only when loading from versions >= Version.pathfindImprovement. -
public byte m_LaneCrossCount
Number of lane crosses (small count). Present as stored data in the struct. -
public Bounds1 blockageBounds
Computed property that converts m_BlockageStart and m_BlockageEnd to normalized Bounds1: new Bounds1(m_BlockageStart * (1/255f), m_BlockageEnd * (1/255f)). -
public Bounds1 cautionBounds
Computed property that converts m_CautionStart and m_CautionEnd to normalized Bounds1: new Bounds1(m_CautionStart * (1/255f), m_CautionEnd * (1/255f)).
{{ Additional notes: - The blockage/caution bytes are stored as 0..255 and converted to float range [0,1] by multiplying by 1/255 (constant 0.003921569f). - Some fields are conditionally serialized/deserialized depending on save-game/engine Version flags to maintain backward compatibility. }}
Properties
-
public Bounds1 blockageBounds { get; }
Returns a Bounds1 constructed from m_BlockageStart/m_BlockageEnd scaled to [0,1]. Useful for quickly checking blocked segment within lane coordinates. -
public Bounds1 cautionBounds { get; }
Returns a Bounds1 constructed from m_CautionStart/m_CautionEnd scaled to [0,1]. Represents an area where caution (reduced speed/behavior) applies.
{{ YOUR_INFO: These are read-only computed properties (no backing float fields) and are cheap conversions from the stored byte pair to floating bounds. Use them when evaluating lane segments for blocking/caution behavior. }}
Constructors
public CarLane()
Default value-type constructor. No explicit custom constructors are defined in source — initialization is typically done by directly setting fields or by the deserialization routine.
{{ YOUR_INFO: As a struct, CarLane uses the default parameterless constructor which initializes numeric fields to zero. Some fields (like m_BlockageStart/m_CautionStart) are set to sentinel values in Deserialize when older versions are detected (e.g., byte.MaxValue/0 to indicate "no range"). }}
Methods
public void Serialize<TWriter>(TWriter writer) where TWriter : IWriter
Writes out the struct's fields in a stable order. Writes:- m_AccessRestriction (Entity)
- m_Flags as uint
- m_DefaultSpeedLimit (float)
- m_SpeedLimit (float)
- m_Curviness (float)
- m_CarriagewayGroup (ushort)
- m_BlockageStart (byte)
- m_BlockageEnd (byte)
- m_CautionStart (byte)
- m_CautionEnd (byte)
- m_FlowOffset (byte)
Note: The writer is expected to handle versioning context externally; fields are always written here (serialization format corresponds to current code expectations).
public void Deserialize<TReader>(TReader reader) where TReader : IReader
Reads fields from reader with compatibility handling:- If reader.context.version >= Version.pathfindAccessRestriction then read m_AccessRestriction.
- Read flags (uint) then later cast to CarLaneFlags and assign to m_Flags.
- Always read m_DefaultSpeedLimit.
- If version >= Version.modifiedSpeedLimit read m_SpeedLimit; otherwise set m_SpeedLimit = m_DefaultSpeedLimit.
- Read m_Curviness and m_CarriagewayGroup.
- If version >= Version.carLaneBlockage read m_BlockageStart and m_BlockageEnd; otherwise set m_BlockageStart = byte.MaxValue and m_BlockageEnd = 0 (meaning no blockage).
- If version >= Version.trafficImprovements read m_CautionStart and m_CautionEnd; otherwise set m_CautionStart = byte.MaxValue and m_CautionEnd = 0 (meaning no caution range).
- If version >= Version.pathfindImprovement read m_FlowOffset.
- Finally, apply a compatibility fix for road-side connections: if reader.context.version < Version.roadSideConnectionImprovements then:
- if (m_Flags & CarLaneFlags.Unsafe) != 0 then m_Flags |= CarLaneFlags.SideConnection
- else m_Flags &= ~CarLaneFlags.SideConnection
{{ YOUR_INFO: - The Deserialize method both reconstructs state and patches older save files to match newer semantics (notably speed limit handling, blockage/caution defaults, and side-connection compatibility). - The Version.* symbols referenced are game-defined version checkpoints used to gate when certain fields/features were introduced. When writing mods that load/save data, respect the game's Version context. - The Serialize method writes the modern set of fields. If you need to produce legacy-compatible saves, additional handling outside this struct may be required. }}
Usage Example
// Create and initialize a new CarLane (example usage in a system or initialization code)
CarLane lane = new CarLane();
lane.m_AccessRestriction = Entity.Null; // no restriction
lane.m_Flags = CarLaneFlags.None;
lane.m_DefaultSpeedLimit = 50f;
lane.m_SpeedLimit = 45f; // temporary reduced speed
lane.m_Curviness = 0.2f;
lane.m_CarriagewayGroup = 0;
lane.m_BlockageStart = byte.MaxValue; // no blockage
lane.m_BlockageEnd = 0;
lane.m_CautionStart = byte.MaxValue; // no caution
lane.m_CautionEnd = 0;
lane.m_FlowOffset = 0;
lane.m_LaneCrossCount = 0;
// Query normalized blockage bounds
Bounds1 blocked = lane.blockageBounds;
if (blocked.min <= blocked.max) {
// Evaluate or respond to blockage
}
// When reading from disk (the game's IReader calls Deserialize automatically in load pipelines)
// The Deserialize method will apply compatibility fixes based on reader.context.version.
{{ YOUR_INFO: Tips for modders: - When modifying lane speed behavior, prefer adjusting m_SpeedLimit at runtime; m_DefaultSpeedLimit is the baseline. - Use blockageBounds / cautionBounds to check relative positions along a lane for triggers such as visual overlays or AI behavior changes. - Be careful when serializing custom data alongside game data; respect the game's versioning to avoid corrupting older saves. - This struct is an ECS component (IComponentData). To add or query CarLane components use the Unity.Entities API used by the game (EntityManager/Systems) rather than storing it separately. }}