Skip to content

Game.Net.AirwayHelpers

Assembly:
Namespace: Game.Net

Type: static class

Base: System.Object

Summary:
AirwayHelpers provides data structures and utility routines used by the game's airpath system (airways) for airplanes and helicopters. It defines in-memory maps (AirwayMap) that store Entity references to airway lanes in a 2D grid, helpers to convert between grid/cell indices and world positions, nearest-lane lookup routines, and a small container (AirwayData) to hold separate maps for helicopters and airplanes. The maps use a NativeArray for tight, GC-free storage and support serialization/deserialization and explicit disposal to avoid native memory leaks.


Fields

  • private int2 m_GridSize
    The grid size (width, height) in cells used by an AirwayMap. Each cell has up to three lane entries (HorizontalZ, HorizontalX, Diagonal). Used for index calculations and clamping.

  • private float m_CellSize
    World-space size of a single grid cell. Used to convert between grid coordinates and world positions.

  • private float m_PathHeight
    Height (Y) used for airway node positions. Returned by GetNodePosition for a given node index.

  • private Unity.Collections.NativeArray<Unity.Entities.Entity> m_Entities
    The packed storage of Entities representing airway nodes/lanes. Length is computed as: (m_GridSize.x * 3 + 1) * m_GridSize.y + m_GridSize.x. This layout reserves three slots per column within each row plus a trailing row/column area for boundaries.

Properties

  • public NativeArray<Entity> entities { get; } (AirwayMap)
    Exposes the underlying NativeArray for read/write access. Important: this is native memory and must be handled appropriately (disposed via Dispose on the containing AirwayMap).

  • public AirwayMap helicopterMap { get; private set; } (AirwayData)
    Map for helicopter airways (grid, lanes, entities).

  • public AirwayMap airplaneMap { get; private set; } (AirwayData)
    Map for airplane airways.

Constructors

  • public AirwayMap(int2 gridSize, float cellSize, float pathHeight, Allocator allocator)
    Creates a new AirwayMap with the given grid size, cell size and path height and allocates the internal NativeArray with the provided Allocator. The internal array length is computed as: (gridSize.x * 3 + 1) * gridSize.y + gridSize.x.

  • public AirwayData(AirwayMap _helicopterMap, AirwayMap _airplaneMap)
    Simple constructor to initialize an AirwayData container with separate helicopter and airplane maps.

Methods

  • public void Dispose() (AirwayMap)
    Disposes the internal NativeArray if it has been created. Must be called when the map is no longer needed to free native memory.

  • public void Serialize<TWriter>(TWriter writer) where TWriter : IWriter (AirwayMap)
    Serializes m_GridSize, m_CellSize, m_PathHeight and the length + contents of the NativeArray to the provided writer. Uses the writer.Write overloads for int2, float and NativeArray.

  • public void Deserialize<TReader>(TReader reader) where TReader : IReader (AirwayMap)
    Reads back grid size, cell size, (conditionally) path height (only if reader.context.version >= Version.airplaneAirways), and reads the array contents. Note: the code reads an int (array length) but ignores it (reads into a discard int) and reads into the existing NativeArray storage.

  • public void SetDefaults(Context context) (AirwayMap)
    Initializes all entries in the internal entity array to Entity.Null.

  • public int2 GetCellIndex(int entityIndex, out LaneDirection direction) (AirwayMap)
    Converts a packed entityIndex (index into m_Entities) into the corresponding 2D cell index (int2) and returns which LaneDirection slot that index refers to. The method decodes the packed layout (3 lane slots per cell plus row/column tail) and adjusts direction for edges.

  • public int GetEntityIndex(int2 nodeIndex, LaneDirection direction) (AirwayMap)
    Computes the packed entity index into m_Entities for a node at nodeIndex and a given LaneDirection. Uses the same layout formula as the constructor to compute the base row offset and then picks the appropriate slot (min(2, direction) for rows inside grid, plain offset for the final boundary row).

  • public PathNode GetPathNode(int2 index) (AirwayMap)
    Returns a PathNode constructed from the appropriate entity in m_Entities for the given index. Handles interior cells, trailing row and trailing column cases.

  • public float3 GetNodePosition(int2 nodeIndex) (AirwayMap)
    Converts a node grid index to a world position (float3). The XZ coordinates are centered around grid center: (nodeIndex - gridSize * 0.5f) * cellSize, and Y is m_PathHeight.

  • public int2 GetCellIndex(float3 position) (AirwayMap)
    Converts a world position to a grid cell index by dividing XZ by cell size, offsetting by grid center, and clamping into [0, gridSize-1].

  • public void FindClosestLane(float3 position, ComponentLookup<Curve> curveData, ref Entity lane, ref float curvePos, ref float distance) (AirwayMap)
    Finds the closest airway lane to a world position. It queries several nearby entity indices (the current cell's HorizontalZ, HorizontalX, Diagonal and neighboring HorizontalZ/X in adjacent cells) and updates the best lane, curve position and best distance.

  • private void FindClosestLaneImpl(float3 position, ComponentLookup<Curve> curveData, ref Entity bestLane, ref float bestCurvePos, ref float bestDistance, int entityIndex) (AirwayMap)
    Helper that checks whether the entity at the given index has a Curve component and computes the distance from the provided position to the Bezier stored in that Curve (using MathUtils.Distance). If closer than bestDistance, updates the best result references.

  • public void Dispose() (AirwayData)
    Disposes both helicopterMap and airplaneMap.

  • enum LaneDirection { HorizontalZ, HorizontalX, Diagonal, DiagonalCross }
    Identifies which lane slot within a cell is referenced. Typically three used inside the grid: HorizontalZ, HorizontalX, Diagonal; DiagonalCross is present as a value but layout code clamps to available slots.

Notes and implementation details: - The underlying entity array layout is unusual: for each row there are (gridSize.x * 3 + 1) slots and there is an additional trailing row that contains only gridSize.x slots. This layout allows storing 3 lane slots per cell plus boundary items. The indexing math in GetCellIndex and GetEntityIndex matches that layout. - Serialization/Deserialization uses Colossal.Serialization IWriter/IReader interfaces and is version aware: pathHeight is only read for readers with context.version >= Version.airplaneAirways. - The code uses ComponentLookup when searching the closest lane: this implies the search is done in a context where ComponentLookup<> is available (ECS context). The Curve component contains a m_Bezier used for distance queries. - Because maps use NativeArray, always call Dispose() to avoid native memory leaks (or wrap in a using-style struct lifecycle).

Usage Example

// Example: create an AirwayMap and find the closest airway lane to a position.
// Note: this is illustrative; actual usage requires ECS context, proper Allocator choice
// (e.g., Allocator.TempJob or Allocator.Persistent) and correct ComponentLookup<Curve>.

int2 gridSize = new int2(128, 128);
float cellSize = 64f;
float pathHeight = 200f;

// Allocate maps (remember to dispose when done)
var helicopterMap = new AirwayHelpers.AirwayMap(gridSize, cellSize, pathHeight, Unity.Collections.Allocator.Persistent);
var airplaneMap = new AirwayHelpers.AirwayMap(gridSize, cellSize, pathHeight + 300f, Unity.Collections.Allocator.Persistent);

var airwayData = new AirwayHelpers.AirwayData(helicopterMap, airplaneMap);

// Initialize entries to Entity.Null
helicopterMap.SetDefaults(default);
airplaneMap.SetDefaults(default);

// Example: find nearest lane around a world position.
// 'curveLookup' must be obtained from an ECS System or ComponentSystemRoot context.
Entity bestLane = Entity.Null;
float bestCurvePos = 0f;
float bestDistance = float.MaxValue;
float3 samplePosition = new float3(1024f, 0f, -512f);

// component lookup example (pseudo):
// ComponentLookup<Curve> curveLookup = world.GetExistingSystem<MySystem>().GetComponentLookup<Curve>(false);

helicopterMap.FindClosestLane(samplePosition, curveLookup, ref bestLane, ref bestCurvePos, ref bestDistance);

if (bestLane != Entity.Null)
{
    // bestLane and bestCurvePos describe the closest airway lane and position on its curve.
}

// Cleanup
airwayData.Dispose();