Skip to content

Game.Pathfind.PathfindJobs

Assembly: Game (pathfinding systems for Cities: Skylines 2)
Namespace: Game.Pathfind

Type: static class (container for nested pathfinding job types and helpers)

Base: System.Object

Summary:
PathfindJobs is a container static class that groups the pathfinding job implementations and internal helper types used by the game's pathfinding system. It includes a set of nested value types and jobs that perform path search, create path results and write those results back into ECS components/buffers. Key items inside this class are: - FullNode, NodeData, HeapData, TargetData: small internal data structures used by the executor. - PathfindExecutor: the main Dijkstra/A* style executor that builds and extracts the search graph, computes costs and constructs final paths. - PathfindJob (Burst-compiled IJob): executes pathfinding for a PathfindActionData and produces PathfindResult(s). - ProcessResultsJob (Burst-compiled IJobParallelFor): writes pathfinding results back to ECS components and buffers (PathOwner, PathInformation, PathElement, PathInformations). The executor uses low-level/unsafe collections (UnsafeList, UnsafeHashMap, UnsafeMinHeap) and is tuned for performance (Burst, Unity.Collections/Mathematics, explicit memory management). When using or adapting these jobs, pay attention to allocation/deallocation, allocator lifetime and thread-safety rules.


Fields

  • private UnsafePathfindData m_PathfindData
    This is the read-only reference the PathfindExecutor keeps to access the game's path/edge data. It is set during Initialize and used heavily by AddTargets, AddConnections, FindEndNode and CreatePath. It points into NativePathfindData.GetReadOnlyData() and must not be used after the executor is released.

  • private UnsafeMinHeap<HeapData> m_Heap
    A low-level min-heap used by PathfindExecutor to store open set entries during the search (HeapData holds cost and node index). The heap is created during Initialize with a chosen capacity and must be disposed by Release to avoid memory leaks.

(Notes: many other private fields exist inside PathfindExecutor and nested structs — node/index lists, UnsafeHashMap for start/end targets, m_NodeData UnsafeList of NodeData, various configuration fields such as m_HeuristicCostFactor, m_MaxTotalCost, m_Allocator, m_Random, masks and flags. They control search behaviour, heuristics and parking handling.)

Properties

  • No public properties exist on the top-level PathfindJobs container. The nested job structs (PathfindJob, ProcessResultsJob) expose public fields (used as parameters) rather than C# properties to keep blittable, Burst-compatible job data.

(Internally, PathfindExecutor and other nested types expose many private/internal state fields — these are not C# properties and are managed directly.)

Constructors

  • public PathfindJobs() (implicit static container — no instance constructors)
    The static class itself has no constructors; work is done via creating and running the nested job structs or by instantiating/initializing PathfindExecutor inside the job bodies.

For nested types: - PathfindExecutor is a value type and is initialized by calling Initialize(...). That method allocates internal UnsafeLists/UnsafeHashMaps and must be paired with Release() when done.

Methods

  • public void Execute() (PathfindJob : IJob)
    Executes the PathfindJob on the current thread (or scheduled by the Job system). The job calls the static Execute(...) helper which:
  • Validates inputs (start/end targets must exist),
  • Creates a PathfindExecutor, calls Initialize(...) and AddTargets(...),
  • Runs the search loop using FindEndNode(...), constructs paths via CreatePath(...),
  • Stores results in the provided action data result list,
  • Releases executor allocations via Release(). Notes: This method is Burst-compiled. Input fields on the job are plain public fields (RandomSeed, NativePathfindData, PathfindHeuristicData, max speeds and the PathfindAction). Use Allocator.Temp or another allocator when calling the static Execute helper; ensure lifetime and thread-safety rules for NativePathfindData and other native collections.

  • public static void Execute(NativePathfindData pathfindData, Allocator allocator, Unity.Mathematics.Random random, PathfindHeuristicData pathfindHeuristicData, float maxPassengerTransportSpeed, float maxCargoTransportSpeed, ref PathfindActionData actionData)
    Static helper used by the IJob implementation. See notes above. It implements high-level flow and the fallback (SkipPathfind) handling. It constructs PathfindExecutor, drives the search and fills PathfindResult entries.

  • public void Initialize(NativePathfindData pathfindData, Allocator allocator, Unity.Mathematics.Random random, PathfindParameters parameters, PathfindHeuristicData pathfindHeuristicData, float maxPassengerTransportSpeed, float maxCargoTransportSpeed) (PathfindExecutor)
    Prepares internal data structures (UnsafeList/UnsafeHashMap/UnsafeMinHeap), computes heuristic factors, configures masks and parking handling and sets up node index bitmaps and heap/list capacities based on the path data sizes. Must be called before AddTargets / FindEndNode.

  • public void Release() (PathfindExecutor)
    Frees/Disposes internal Unsafe containers created in Initialize. Always call (or ensure Release gets called) to avoid native memory leaks.

  • public void AddTargets(UnsafeList<PathTarget> startTargets, UnsafeList<PathTarget> endTargets, ref ErrorCode errorCode) (PathfindExecutor)
    Adds start/end targets to internal maps and lists, computes which side to invert (search direction), sets up forward/backward masks, computes m_CostOffset and m_MaxTotalCost and prepares the initial node queue. Writes error codes (TooManyEndAccessRequirements, MultipleStartResults, etc.) when appropriate.

  • public Bounds3 GetTargetBounds(UnsafeList<PathTarget> pathTargets, out float minCost, out int accessRequirement, out bool multipleRequirements) (PathfindExecutor)
    Examines a list of PathTarget entries to produce a bounding box of their positions, the minimal provided cost and access requirements. Used for heuristics and to detect multiple access requirements.

  • public bool FindEndNode(out int endNode, out float travelCost, out int graphTraversal) (PathfindExecutor)
    Main search loop: extracts nodes from the heap, expands connections, checks for end targets and returns when a valid end node is found. Provides travel cost and counts graph traversal. Will respect m_MaxTotalCost and m_MaxResultCount.

  • private void AddConnections(...), private void AddHeapData(...), private float CalculateCost(...), private float CalculateTotalCost(...), private bool IsValidDelta(...), private bool DisallowConnection(...) (PathfindExecutor internals)
    These methods compute edge costs using PathSpecification costs + weights, apply heuristic distance to the end bounds, validate curve delta segments against blockages/rules, enforce method/parking/access rules and insert/update nodes into the open set.

  • public void CreatePath(int endNode, ref UnsafeList<PathfindPath> path, out float distance, out float duration, out int pathLength, out Entity origin, out Entity destination, out PathMethod methods) (PathfindExecutor)
    Backtracks from an end node through NodeData.SourceIndex chain to build a PathfindPath sequence, computes path distance/duration/method mask and writes origin/destination Entities. Handles path inversion (when the search was inverted at AddTargets time) and sets the PathStart flag on the first PathElement. If path buffer is provided it fills it with PathfindPath entries.

  • public void Execute(int index) (ProcessResultsJob : IJobParallelFor)
    Processes a ResultItem at index: writes PathElements into PathElement buffers, updates PathOwner and PathInformation components, copies per-result PathfindResult entries into PathInformations buffers. The job uses native ECS ComponentLookup / BufferLookup (native collections) and must be invoked with correct safety restrictions (NativeDisableParallelForRestriction is used for writes).

(There are many more internal/private helper methods and small structs inside PathfindJobs — the above are the primary externally-relevant entry points and the high-level flow.)

Usage Example

// Example (simplified): run a pathfind synchronously on the current thread.
// Fill placeholders with actual game data from your mod's context.

Game.Pathfind.PathfindJobs.PathfindJob job = new Game.Pathfind.PathfindJobs.PathfindJob {
    m_RandomSeed = new RandomSeed(12345u),
    m_PathfindData = myNativePathfindData,               // NativePathfindData
    m_PathfindHeuristicData = myHeuristicData,           // PathfindHeuristicData
    m_MaxPassengerTransportSpeed = 20f,                  // meters/sec (example)
    m_MaxCargoTransportSpeed = 15f,                      // meters/sec (example)
    m_Action = myPathfindAction                          // PathfindAction wrapper with PathfindActionData inside
};

// Run immediately (IJob.Run / Execute inline)
job.Execute(); // In actual mod code you might schedule the job instead using JobHandle

// Alternatively call the static helper directly:
// PathfindJobs.PathfindJob.Execute(pathfindData, Allocator.Temp, random, heuristicData, maxPass, maxCargo, ref actionData);

Notes and tips - PathfindExecutor uses many Unsafe collections (UnsafeList, UnsafeHashMap, UnsafeMinHeap). These are high-performance but require deterministic allocation/disposal. Always call Release() (or rely on the job's Execute flow which calls Release) to free native memory. - The jobs are Burst-compiled (BurstCompile attributes) and use blittable public fields. Avoid adding managed references to job structs. - The search respects many flags and pathfinding parameters (parking reset, reduced costs, access requirements, ignored rules, Forward/Backward inversion). Familiarize yourself with PathfindParameters, PathfindFlags, EdgeFlags and PathMethod to configure searches correctly. - ProcessResultsJob writes directly to ECS components and buffers — ensure the ComponentLookup/BufferLookup are created with appropriate write permissions and lifetime when scheduling this job.

If you want, I can generate a more detailed reference for any of the nested types (FullNode, NodeData, PathfindExecutor, PathfindJob, ProcessResultsJob) including all fields, parameter explanations and important branching logic.