Skip to content

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. }}