Game.Simulation.CarLaneSelectIterator
Assembly: Game
Namespace: Game.Simulation
Type: struct (public)
Base: System.ValueType
Summary:
CarLaneSelectIterator is a utility struct used during car navigation to evaluate and choose optimal sub-lanes for vehicles. It computes per-sub-lane costs (including lane objects, reservations, lane flags and lane-switch penalties), updates the vehicle's optimal lane selection and change-lane state, and can draw debug visualizations of computed costs. It operates on ECS lookups (ComponentLookup / BufferLookup) and a float cost buffer provided by a CarLaneSelectBuffer.
Fields
-
public ComponentLookup<Owner> m_OwnerData
Lookup accessor to read Owner component for a lane entity. Used to get the buffer index (owner) that holds sub-lane entries. -
public ComponentLookup<Lane> m_LaneData
Lookup accessor for lane component data (geometry, nodes, bezier/curve info) for sub-lane entities. -
public ComponentLookup<CarLane> m_CarLaneData
Lookup for CarLane component (per-sub-lane flags used to influence drive cost, e.g., queue, invert). -
public ComponentLookup<SlaveLane> m_SlaveLaneData
Lookup for SlaveLane meta-data describing sub-lane ranges (min/max index, flags) for a given lane entity. -
public ComponentLookup<LaneReservation> m_LaneReservationData
Lookup for lane reservation data. If present on a sub-lane it adds priority-based cost. -
public ComponentLookup<Moving> m_MovingData
Lookup to detect moving objects/entities. Used when assessing cost contribution of lane objects (moving objects reduce cost penalty). -
public ComponentLookup<Car> m_CarData
Lookup for Car components to detect queued cars and other car-specific flags that adjust lane object costs. -
public ComponentLookup<Controller> m_ControllerData
Lookup to detect controller entities attached to lane objects; used to avoid self-counting when computing cost. -
public BufferLookup<SubLane> m_Lanes
Buffer lookup mapping an owner (from Owner) to the DynamicBufferwhich enumerates sub-lanes belonging to a logical lane. -
public BufferLookup<LaneObject> m_LaneObjects
Buffer lookup of lane objects attached to a particular sub-lane. Used to evaluate object-related cost penalties. -
public Entity m_Entity
Context entity (typically the car entity) used to exclude itself from some lane-object cost evaluations. -
public Entity m_Blocker
Optional blocker entity. When set, special handling in object cost calculation treats the blocker differently (used when checking first/early index lanes). -
public int m_Priority
Priority value used when computing relative lane-priority cost (higher priority reduces penalty relative to this value). -
public Game.Net.CarLaneFlags m_ForbidLaneFlags
Flags marking lanes that are actively forbidden. Presence of these flags on a lane influences GetLaneDriveCost. -
public Game.Net.CarLaneFlags m_PreferLaneFlags
Flags marking preferred lane characteristics. Lanes that do not match preferred flags get a small cost increase, forbidden lanes get larger cost. -
private NativeArray<float> m_Buffer
Internal buffer of floating-point lane costs (flat list of costs for sub-lanes from recent CalculateLaneCosts calls). Provided by CarLaneSelectBuffer.Ensure(). -
private int m_BufferPos
Write position/index into m_Buffer for appending cost entries. -
private float m_LaneSwitchCost
Working multiplier used to compute lane-switch penalty (varies per slave-lane and is temporarily calculated for a given evaluation). -
private float m_LaneSwitchBaseCost
Cumulative base cost used across calculations; incremented/decremented slightly between calls to bias selection stability. -
private Entity m_PrevLane
Stores previously selected sub-lane (or change-lane) so UpdateOptimalLane and drawing logic can reference the prior lane and compute relative costs or visualize transitions.
Properties
- None (this struct exposes fields directly; there are no properties).
Constructors
public CarLaneSelectIterator()
Default struct constructor (value-type). Typical usage is to instantiate default and then assign ComponentLookup/BufferLookup fields plus set buffer via SetBuffer(). All lookups and fields must be initialized by the caller before use.
Methods
-
public void SetBuffer(ref CarLaneSelectBuffer buffer)
Ensures and stores the internal NativeArrayused for cost accumulation. Must be called before any CalculateLaneCosts calls that write into the internal buffer. -
public void CalculateLaneCosts(CarNavigationLane navLaneData, int index)
Computes and appends costs for each sub-lane within the SlaveLane range for the provided navigation lane when there is no next lane context. Skips reserved/fixed lanes and slave-less lanes. Costs include lane-object penalties, lane reservation priority cost, and drive-cost derived from CarLane flags. -
private float CalculateLaneObjectCost(float laneObjectCost, int index, Entity lane, Game.Vehicles.CarLaneFlags laneFlags)
Computes cost contributed by lane objects on a specific sub-lane. If index < 2 and m_Blocker is set, treats the blocker specially (calls other overload); otherwise multiplies laneObjectCost by number of objects. Excludes objects as appropriate. -
private float CalculateLaneObjectCost(float laneObjectCost, Entity lane, float minCurvePosition, Game.Vehicles.CarLaneFlags laneFlags)
Calculates cost from lane objects whose curve position is after minCurvePosition; excludes the calling entity and its controller. Summation uses CalculateLaneObjectCost(LaneObject, ...). -
private float CalculateLaneObjectCost(LaneObject laneObject, float laneObjectCost, Game.Vehicles.CarLaneFlags laneFlags)
Lower-level decision for a single LaneObject. If the lane object is moving, returns laneObjectCost. If it's a stationary object: if it's a queued car and queue flag is allowed, returns laneObjectCost. Otherwise returns a large cost (lerp between 10,000,000 and 9,000,000 by curve position), effectively making lanes with static obstacles extremely expensive. -
public void CalculateLaneCosts(CarNavigationLane navLaneData, CarNavigationLane nextNavLaneData, int index)
Primary method used when both current and next navigation lanes are known. Computes combined costs considering transitions between current sub-lanes and next sub-lanes, lane-switch penalties (GetLaneSwitchCost), lane object costs, lane reservations and drive flags. It handles several cases: - When nextNavLaneData is a regular target, it computes matching sub-lane ranges and cross-references the previously filled buffer entries for costs of next lane to compute transition costs.
- When nextNavLaneData has TransformTarget or is reserved/fixed, it falls back to local-only cost calculations.
-
Increments m_LaneSwitchBaseCost slightly after running (to add stability bias).
-
private float GetLaneSwitchCost(int numLanes)
Returns lane-switch penalty as (numLanes^3) * m_LaneSwitchCost. Heavier penalty for switching across multiple lanes. -
private float GetLanePriorityCost(int lanePriority)
Returns cost penalty based on lane reservation priority relative to m_Priority. Only penalizes lanes whose priority is higher than the iterator's priority. -
private float GetLaneDriveCost(Game.Net.CarLaneFlags flags)
Computes a drive-related cost multiplier depending on whether lane flags match preferred flags, or are forbidden. This uses a somewhat involved math.select expression: if flags & m_ForbidLaneFlags != 0, a larger penalty is returned (value depends on m_Priority), otherwise a small penalty (0 or 0.4f) if lane does not match m_PreferLaneFlags. -
public void UpdateOptimalLane(ref CarCurrentLane currentLane, CarNavigationLane nextNavLaneData)
Given the current lane state for an individual car, evaluates the local slave-lane group and the potential transitions to the next navigation lane, then updates currentLane.m_ChangeLane and currentLane.m_LaneFlags accordingly. Chooses the minimal cost target while taking into account current change progress and lane-switch costs. Also sets m_PrevLane and resets m_LaneSwitchCost. -
private Game.Vehicles.CarLaneFlags GetTurnFlags(Entity currentLane, int currentIndex, int changeIndex)
Helper used to set turn flags (TurnLeft / TurnRight) depending on whether the selected changeIndex is left or right of currentIndex. Accounts for Invert flags on the CarLane to reverse direction interpretation. -
public void UpdateOptimalLane(ref CarNavigationLane navLaneData)
Simpler optimal-lane update used when working with navigation lane records (no per-car current lane context). Uses the previously computed buffer data to pick the best sub-lane index for navLaneData.m_Lane. Adjusts m_LaneSwitchCost based on slave-lane flags and updates m_PrevLane; also increments/decrements base cost slightly to influence stability. -
public void DrawLaneCosts(CarCurrentLane currentLaneData, CarNavigationLane nextNavLaneData, ComponentLookup<Curve> curveData, GizmoBatcher gizmoBatcher)
Entry used to prepare drawing state for a per-car current lane: sets m_PrevLane from current or change lane. (Primary drawing logic is in the other overload.) -
public void DrawLaneCosts(CarNavigationLane navLaneData, ComponentLookup<Curve> curveData, GizmoBatcher gizmoBatcher)
Iterates sub-lanes in the slave-lane range and calls DrawLane for each sub-lane, using the cost previously recorded in m_Buffer. If lane is reserved/fixed, the method visualizes only the active lane with zero cost and all others as very expensive. -
private void DrawLane(Entity lane, float2 curvePos, ComponentLookup<Curve> curveData, GizmoBatcher gizmoBatcher, float cost)
Converts a cost into a color ramp (black for very expensive, cyan->yellow->red for increasing costs), extracts the bezier segment for the given curve position, and uses GizmoBatcher.DrawCurve to visualize the lane and its cost. Used for debugging lane selection.
Usage Example
// Example inside a system or processing function where lookups and buffer are available:
CarLaneSelectBuffer selectBuffer = default;
CarLaneSelectIterator iter = default;
// assign lookups (these are prepared by the ECS system / Job)
// iter.m_OwnerData = ownerLookup;
// iter.m_LaneData = laneLookup;
// iter.m_CarLaneData = carLaneLookup;
// iter.m_SlaveLaneData = slaveLaneLookup;
// iter.m_LaneReservationData = laneReservationLookup;
// iter.m_MovingData = movingLookup;
// iter.m_CarData = carLookup;
// iter.m_ControllerData = controllerLookup;
// iter.m_Lanes = lanesBufferLookup;
// iter.m_LaneObjects = laneObjectsBufferLookup;
iter.m_Entity = carEntity;
iter.m_Blocker = blockerEntity;
iter.m_Priority = vehiclePriority;
iter.m_ForbidLaneFlags = forbiddenFlags;
iter.m_PreferLaneFlags = preferredFlags;
iter.m_LaneSwitchBaseCost = 0.0f;
// prepare / ensure cost buffer
iter.SetBuffer(ref selectBuffer);
// compute costs for a navigation lane (single-lane scenario)
iter.CalculateLaneCosts(navLaneData, index);
// or compute costs with next lane context
iter.CalculateLaneCosts(navLaneData, nextNavLaneData, index);
// then update car's optimal lane
iter.UpdateOptimalLane(ref currentLane, nextNavLaneData);
// optionally draw costs for debugging
iter.DrawLaneCosts(navLaneData, curveLookup, gizmoBatcher);
Notes and tips: - All ComponentLookup and BufferLookup fields must be initialized with the current world/state prior to use. In Jobs ensure you use the thread-safe variants and update permissions (ReadOnly / Write) appropriately. - The iterator writes into an externally-provided float buffer (CarLaneSelectBuffer). Caller must ensure enough capacity and preserve buffer positions between calls as expected by the selection flow. - Lane-switch cost is cubic in the number of lanes switched and includes dynamic multipliers; small tweaks to m_LaneSwitchBaseCost (the struct updates it) affect lane stability and the tendency to change lanes frequently. - Use DrawLaneCosts only for debug visuals (GizmoBatcher) to inspect resulting costs in-editor or during runtime debugging.