Skip to content

Game.Pathfind.UnsafePathfindData

Assembly:
Namespace: Game.Pathfind

Type: struct

Base: IDisposable

Summary:
UnsafePathfindData is a low-level, performance-oriented container used by the pathfinding system to store edges, nodes and their connections. It uses Unity unsafe collections and a custom UnsafeHeapAllocator to pack connection metadata into contiguous unmanaged memory blocks for minimal overhead. Because it manipulates unmanaged memory and exposes raw pointers, it must be created with a Unity Allocator and explicitly disposed to avoid native memory leaks. This type is intended for internal/modding use where high performance and compact memory layout are required (Burst-compatible annotations are present).


Fields

  • public UnsafeList<Edge> m_Edges
    Stores the list of Edge structs. Edges are stored densely; removed edges may be recycled via m_FreeIDs.

  • public UnsafeList<EdgeID> m_FreeIDs
    List of recycled EdgeID slots that can be reused when creating new edges.

  • public UnsafeHashMap<Entity, EdgeID> m_PathEdges
    Map from owner Entity to primary EdgeID.

  • public UnsafeHashMap<Entity, EdgeID> m_SecondaryEdges
    Map from owner Entity to secondary EdgeID.

  • public UnsafeHashMap<PathNode, NodeID> m_NodeIDs
    Map from PathNode (position + flags) to NodeID (index into connection heap).

  • public UnsafeHashMap<NodeID, PathNode> m_PathNodes
    Reverse map from NodeID to PathNode.

  • private UnsafeHeapAllocator m_ConnectionAllocator
    Allocator managing blocks of connection metadata (counts, capacities, connections and access requirements). Allocation units are stored as small heap blocks referenced by NodeID.m_Index.

  • private unsafe void* m_Connections
    Raw pointer to contiguous memory holding "forward" connection metadata for all nodes (counts, capacities, connection indices and access requirements). Layout is compact and index-based.

  • private unsafe void* m_ReversedConnections
    Raw pointer to contiguous memory holding "reversed" connection metadata (edges that arrive to the node).

  • private int m_NodeCount
    Number of currently allocated node entries (number of NodeIDs present in the maps).

  • private readonly Allocator m_AllocatorLabel
    Allocator label used when allocating m_Connections / m_ReversedConnections with UnsafeUtility.

  • private const int NODE_META_SIZE = 1
    Internal constant used by connection allocator logic (metadata size per entry).

Properties

  • (None)
    This struct does not expose C# auto-properties. It exposes methods to query and mutate stored data. Note: several methods return refs (e.g., GetEdge, GetConnectionCount) to allow direct in-place mutation.

Constructors

  • public UnsafePathfindData(Allocator allocator)
    Initializes all internal containers and allocators:
  • Creates initial UnsafeList and UnsafeHashMap instances.
  • Initializes the UnsafeHeapAllocator and allocates initial m_Connections and m_ReversedConnections buffers.
  • Sets m_AllocatorLabel for later frees and sets m_NodeCount to 0.
  • Choose an appropriate Unity Allocator (e.g., Allocator.Persistent) for lifetime expectations.

Methods

  • public unsafe void Dispose()
    Frees all managed native containers and unsafe memory (lists, hash maps, connection allocator, and the allocated m_Connections/m_ReversedConnections buffers). MUST be called to avoid native memory leaks.

  • public void Clear()
    Clears all containers but keeps allocated buffers (lists/ maps emptied, connection allocator cleared). m_NodeCount reset to 0. Useful to reuse the structure without deallocation.

  • public unsafe void GetMemoryStats(out uint used, out uint allocated)
    Returns approximate used and allocated bytes based on current capacities and connections. Useful for diagnostics/profiling.

  • public int GetNodeIDSize()
    Returns the one-past-highest-used address from the connection allocator (size indicator of connection heap), useful for sizing or debugging.

  • public EdgeID CreateEdge(PathNode startNode, PathNode middleNode, PathNode endNode, PathSpecification specification, LocationSpecification location)
    Creates and registers a new edge:

  • Reuses an ID from m_FreeIDs if available or appends a new Edge to m_Edges.
  • Initializes node connections (start / middle / end) depending on EdgeFlags (Forward, Backward, AllowMiddle).
  • Adds forward connections into m_Connections and reversed connections into m_ReversedConnections as appropriate.
  • Stores curve positions, specification and location in the Edge and returns the EdgeID.

  • public void UpdateEdge(EdgeID edgeID, PathNode startNode, PathNode middleNode, PathNode endNode, PathSpecification specification, LocationSpecification location)
    Updates an existing edge's nodes, flags and access requirements:

  • Computes deltas between old and new flags and node positions.
  • Removes/Resizes/Re-adds forward/reversed connections as needed.
  • Updates access requirements where changed.
  • Updates stored curve positions, specification and location.

  • public void SetEdgeDirections(EdgeID edgeID, PathNode startNode, PathNode endNode, bool enableForward, bool enableBackward)
    Enables/disables forward/backward directions for an existing edge. Adds/removes corresponding forward and reversed connections and flips flags. Cleans up node IDs if both directions are disabled.

  • public void DestroyEdge(EdgeID edgeID)
    Removes an edge and its connections:

  • Removes forward/reversed connections depending on flags.
  • If the edge is the last in m_Edges, removes it from the list; otherwise clears its slot and pushes its ID to m_FreeIDs for reuse.

  • public void AddEdge(Entity owner, EdgeID edgeID)
    Registers owner as the primary owner of edgeID (stores in m_PathEdges and sets Edge.m_Owner).

  • public void AddSecondaryEdge(Entity owner, EdgeID edgeID)
    Registers a secondary edge for owner (m_SecondaryEdges + Edge.m_Owner).

  • public bool GetEdge(Entity owner, out EdgeID edgeID)
    Tries to retrieve primary EdgeID for the owner.

  • public bool GetSecondaryEdge(Entity owner, out EdgeID edgeID)
    Tries to retrieve secondary EdgeID for the owner.

  • public bool RemoveEdge(Entity owner, out EdgeID edgeID)
    Removes mapping from owner to EdgeID in primary map and returns the removed EdgeID.

  • public bool RemoveSecondaryEdge(Entity owner, out EdgeID edgeID)
    Removes mapping from owner to EdgeID in the secondary map.

  • public unsafe void SwapConnections()
    Swaps the m_Connections and m_ReversedConnections pointers. Useful when the system wants to flip which side is treated as forward vs reversed without copying memory.

  • private NodeID AddConnection(PathNode pathNode, EdgeID edgeID, int accessIndex)
    Adds a forward connection entry for a PathNode:

  • If a NodeID already exists, ensures capacity and appends a connection+access entry.
  • Otherwise allocates a new connections block via CreateConnections and stores the NodeID <> PathNode mapping.

  • private NodeID AddReversedConnection(PathNode pathNode, EdgeID edgeID, int accessIndex)
    Same as AddConnection but for reversed connection array.

  • private void RemoveConnection(NodeID nodeID, EdgeID edgeID)
    Removes a forward connection entry for a node. If both forward and reversed counts become zero, the NodeID is removed and its connection block destroyed.

  • private void RemoveReversedConnection(NodeID nodeID, EdgeID edgeID)
    Removes a reversed connection; symmetric to RemoveConnection.

  • private void UpdateAccessRequirement(NodeID nodeID, EdgeID edgeID, int accessIndex)
    Updates the access requirement integer for a forward connection matching the given edge index.

  • private void UpdateReversedAccessRequirement(NodeID nodeID, EdgeID edgeID, int accessIndex)
    Updates the access requirement for a reversed connection.

  • private NodeID CreateConnections(int connectionCapacity)
    Allocates a new connection block of the requested capacity from m_ConnectionAllocator and initializes forward/reversed counts and capacities for the new NodeID.

  • private void ResizeConnections(ref NodeID nodeID, int connectionCapacity)
    Allocates a larger block, copies existing forward and reversed connection data into the new block, updates Edge references that pointed to the old block to point to the new NodeID index, and releases the old block.

  • private void DestroyConnections(NodeID nodeID)
    Releases the connection block associated with nodeID back to the connection allocator.

  • private unsafe UnsafeHeapBlock AllocateConnections(int connectionCapacity)
    Internal helper that ensures the connection allocator can satisfy an allocation. If the allocator must grow, it resizes the allocator and reallocates the m_Connections / m_ReversedConnections buffers (copying existing memory) to reflect the new Size. Returns an allocated UnsafeHeapBlock.

  • [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref Edge GetEdge(EdgeID edgeID)
    Returns a direct reference to the Edge at edgeID for in-place mutation.

  • [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe ref ushort GetConnectionCount(NodeID nodeID)
    Returns a reference to the ushort forwarding connection count for nodeID inside the m_Connections buffer.

  • [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe ref ushort GetReversedConnectionCount(NodeID nodeID)
    Returns reference to reversed connection count from m_ReversedConnections.

  • [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe ref ushort GetConnectionCapacity(NodeID nodeID)
    Returns reference to forward connection capacity stored in m_Connections.

  • [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe ref ushort GetReversedConnectionCapacity(NodeID nodeID)
    Returns reference to reversed connection capacity stored in m_ReversedConnections.

  • [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe ref int GetConnection(NodeID nodeID, int connectionIndex)
    Returns a reference to the connection (edge index) at the given connectionIndex for nodeID within m_Connections.

  • [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe ref int GetReversedConnection(NodeID nodeID, int connectionIndex)
    Returns a reference to a reversed connection (edge index) entry.

  • [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe ref int GetAccessRequirement(NodeID nodeID, int connectionIndex)
    Returns reference to the access requirement int paired with a forward connection.

  • [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe ref int GetReversedAccessRequirement(NodeID nodeID, int connectionIndex)
    Returns reference to the access requirement for a reversed connection.

Notes: - Many methods return ref to unmanaged memory—be careful when using these references across allocations/resizes (resizing the connection allocator can move memory and invalidate existing references). - This struct is not GC-managed and is unsafe by design; use with care in mod code. Prefer to call Clear/Dispose appropriately and avoid capturing refs beyond safe lifetimes.

Usage Example

// Example usage in a mod (pseudo-code, requires Unity ECS types):
UnsafePathfindData pathData = new UnsafePathfindData(Allocator.Persistent);

try
{
    // Use pathData to create edges, update, query memory stats, etc.
    uint used, allocated;
    pathData.GetMemoryStats(out used, out allocated);
    Debug.Log($"Path memory used={used}, allocated={allocated}");

    // Create and manage edges (PathNode/PathSpecification types would come from the game's API)
    // EdgeID eid = pathData.CreateEdge(startNode, middleNode, endNode, specification, location);
    // pathData.AddEdge(ownerEntity, eid);
}
finally
{
    // Always dispose to free native memory
    pathData.Dispose();
}