Path Request API
Overview
The Path Requests API provides multiple methods for requesting pathfinding operations, from simple synchronous calls to advanced asynchronous job management.
Simple Path Request
--> GetPath() will immediately return a path and is the easiest way but is synchronous:
var pathConfig = new PathConfig()
{
CollapseSkips = true,
UseClosestTarget = false,
QueryDynamic = false
};
// Generate immediately:
List<Vector3> curPath = grid.GetPath(transform.position, target.position, pathConfig);
Recommended Workflow
--> Queuing paths is the most reliable (threaded) but takes a bit more maneuvering:
List<Vector3> curPath = null;
var pathRequest = new PathRequest(transform.position, target.position, pathConfig, result =>
{
curPath = result.Path;
});
grid.RequestPathQueued(pathRequest); // The callback will be executed when the job is complete
Configuration
Before jumping into the API, it's important to know the extra path configuration options. We'll discuss "Closest Target" here and "Collapse Skips" here. "Query Dynamic" is covered in Dynamic Obstacles.
PathConfig
Configuration options for path generation.
public struct PathConfig
{
public bool CollapseSkips; // Expand jump points into full paths
public bool QueryDynamic; // Check dynamic obstacles
public bool UseClosestTarget; // Find closest reachable tile if target blocked
}
| Option | Default | Description |
|---|---|---|
CollapseSkips |
true |
Expand JPS jump points into individual tiles for smooth movement |
QueryDynamic |
true |
Include dynamic obstacles in pathfinding |
UseClosestTarget |
true |
If target is blocked, pathfind to nearest walkable tile |
Closest Target
This configuration parameter will ensure that when pathfinding to a target, if it is blocked or not reachable a path is still returned pathing to the most promising tile (by f-score). This is especially helpful when using Dynamic Obstacles, or when the target may be blocked but we still want to get an approximate path to near the target.
Blocked Start/Target
When "closest target" is not used, paths are STRICT. If the start position is blocked by an obstacle on the static collision matrix OR the target position is blocked by an obstacle on the static or dynamic collision matrix, the path returned will be empty.
Collapse Skips
For many systems, paths need to be contiguous blocks, but jump point algorithms like JPS4 by nature skip nodes in the path during generation. This configuration parameter will ensure after a job completes, the resulting path is converted to contiguous connected tiles and jump skips are collapsed.
Collapse Skips
- True: Path includes every tile (required for grid-based movement)
- False: Path only includes jump points (for visualization/debugging)
- Only affects JPS algorithms (A* always returns full paths)
Path Requests
PathRequest
A path request wrapper with configuration and callback. OnComplete is called when a pathing job is completed regardless of its result / cancellation.
public class PathRequest
{
public Vector3 Start;
public Vector3 Target;
public Action<PathResult> OnComplete;
public PathConfig Config;
}
public PathRequest(
Vector3 start,
Vector3 target,
Action<PathResult> onComplete,
bool collapseSkips = true,
bool queryDynamic = true,
bool useClosestTarget = true
)
public PathRequest(
Vector3 start,
Vector3 target,
PathConfig config,
Action<PathResult> onComplete
)
PathResult
The result of a path request, including an output path and a record of the Config used to generate it. Status is important if the grid changes while a path is queued and a job needs to be re-queued.
public struct PathResult
{
public EPathJobStatus Status; // Success/failure status
public List<Vector3> Path; // Resulting world-space path
public PathConfig Config; // Configuration used
}
Path Job Status
public enum EPathJobStatus
{
Success, // Path found successfully
Cancelled_Rebuild, // Grid was rebuilt during pathfinding
Cancelled_Lifetime, // Grid was destroyed/disabled
Failed // No path found or error occurred
}
GetPath()
Get a path immediately (synchronous), blocking until completion.
This is great for quick, single use path finding, if the grid is small, or if there aren't many agents and you are yielding in between.
public List<Vector3> GetPath(
Vector3 start,
Vector3 target,
PathConfig config
)
Parameters:
start: Start position in world spacetarget: Target position in world spaceconfig: Path configuration options
Returns: List<Vector3> containing the path in world space (empty if no path found)
Example: Simple Path Request
var pathConfig = new PathConfig()
{
CollapseSkips = true,
UseClosestTarget = false,
QueryDynamic = false
};
// Generate immediately:
List<Vector3> curPath = grid.GetPath(transform.position, target.position, pathConfig);
GetPathAsync()
Get a path asynchronously using a coroutine.
If you are using
Awaitableor a library likeCysharp.UniTaskyou can convert coroutines to any needed Unity "async" operations with theSystem.Taskconventions.
public IEnumerator GetPathAsync(PathRequest request)
Parameters:
request: This is aPathRequestcontaining start, target, config, and a completion callback.
Example: Coroutine Path Request
List<Vector3> curPath = null;
var pathConfig = new PathConfig()
{
CollapseSkips = true,
UseClosestTarget = false,
QueryDynamic = false
};
var pathRequest = new PathRequest(transform.position, target.position, pathConfig, result =>
{
curPath = result.Path;
});
var handle = StartCoroutine(grid.GetPathAsync(pathRequest));
Job Queue
The easiest way to queue and wait for multiple jobs without blocking the main thread or yielding frames is using the GridBuilder's Job Queue system.
This is using Burst Job system to complete multi-threaded operations using the
maxConcurrentJobsfield on theGridBuilderobject. Tune this depending on the size of your grid, number of agents, and target platform. See Grid Builder Configuration for more.
Automatic Processing
The queue automatically schedules new jobs up to maxConcurrentJobs and completes callbacks on the main thread.
RequestPathQueued
Add a path request to the managed job queue for automatic processing.
public void RequestPathQueued(PathRequest request)
Parameters:
request: This is aPathRequestthat will be queued and processed automatically
Example: Queued Path Requests
List<Vector3> curPath = null;
var pathConfig = new PathConfig()
{
CollapseSkips = true,
UseClosestTarget = false,
QueryDynamic = false
};
var pathRequest = new PathRequest(transform.position, target.position, pathConfig, result =>
{
curPath = result.Path;
});
grid.RequestPathQueued(pathRequest); // The callback will be executed when the job is complete
Queue Status
public int maxConcurrentJobs = 8; // Inspector configurable
The queue automatically manages jobs by:
- Scheduling new jobs when slots are available
- Checking for completed jobs every frame
- Invoking callbacks on the main thread
- Marking requests dirty if the grid is re-built while executing
WaitForAllJobs()
Wait until all queued and active jobs complete.
public IEnumerator WaitForAllJobs()
Waiting for Batch Completion
foreach (var agent in agents)
{
PathRequest request = agent.GetPathRequest(); // Here "agent" handles the callbacks on completion
gridBuilder.RequestPathQueued(request);
}
// Wait for all to finish
yield return gridBuilder.WaitForAllJobs();
WaitForAllJobs
Calling WaitForAllJobs can be dangerous if you have more than one object queuing jobs at once, since processing jobs can take multiple frames. Alternates are counting remaining jobs on your own semaphore-like approach (remaining-- within the callback), or using the RequestPath() JobHandle approach manually and batching Jobs in a group.
Job Cancellation
Jobs are automatically cancelled when:
- Grid is rebuilt via
Build()→ Status:Cancelled_Rebuild - Grid is destroyed or disabled → Status:
Cancelled_Lifetime
If a job is running and static collision is re-built, it will be "invalidated." The callback is still executed but the result is
PathResult.EPathJobStatus.Cancelled_Rebuild. In this case the resulting path isnull.
Manual cancellation:
// Cancel all pending jobs (not started yet)
private void CancelPendingJobs(PathResult.EPathJobStatus reason)
// Cancel all active jobs (currently running)
public void CancelActiveJobs(PathResult.EPathJobStatus reason)
Active Job Cancellation
CancelActiveJobs() forces completion on the main thread and should be avoided when possible. Let jobs finish naturally when possible.
Advanced Usage
Grid-Space Pathfinding
For working directly with grid coordinates:
public bool TryGetGridPath(
ref NativeList<int2> pathResult,
int2 gridStart,
int2 gridTarget,
PathConfig config
)
RequestPath()
Get direct access to the Unity Job System and use the internal scheduling without the queue system.
public PathHandle RequestPath(
int2 start,
int2 target,
PathConfig config,
Allocator allocator = Allocator.TempJob
)
Parameters:
start: Start position in grid spacetarget: Target position in grid spaceconfig: Path configurationallocator: Memory allocator for the job (default:TempJob)
Returns: PathHandle with job handle and result arrays
PathHandle
Internal wrapper with a JobHandle that tracks a pathfinding job request.
public struct PathHandle : IDisposable
{
public JobHandle Handle; // Handle for scheduled pathfinding job.
public NativeList<int2> Path; // Output Path of grid points (this may not be collapsed for algorithms w/ skip nodes)
public NativeList<JPSDebugStep> DebugSteps; // Output debug info on completion
public bool IsCompleted; // Status of the job
public void Complete(); // Immediately complete the JobHandle (synchronous)
}