BeginFindPath(NavQueryBuffer, NavLocation, NavLocation, int, NativeArray<float>)
Initiates a pathfinding operation between two locations on the NavMesh.
Read time 4 minutesLast updated 20 days ago
Definition
- Type: Method
- Namespace: Unity.AI.Navigation.LowLevel
- Assembly: UnityEngine.AIModule
public readonly NavQueryStatus BeginFindPath(NavQueryBuffer queryBuffer, NavLocation start, NavLocation end, int areaMask = -1, NativeArray<float> costs = default)
Parameters
The NavQueryBuffer used to store intermediate node data for this search operation.
The start location on the NavMesh for the path.
The location on the NavMesh where the path ends.
Bitmask with values of 1 at the indices of areas that can be traversed, and values of 0 for areas that aren't traversable. The default value is NavMesh.AllAreas.
Array of custom cost values for all of the 32 possible area types. Each value must be at least . The default value is the set of area costs configured in the project settings.
1.0fReturns
Type | Description |
|---|---|
| NavQueryStatus | A bitfield with one of the following three main flags set: |
Remarks
The path always begins at the specified location. If the desired end location isn't directly accessible, the search algorithm tries to find a valid location nearby.
Calling this method overrides the progress made by the specified in its previous pathfinding operation. Each NavQueryBuffer stores its own progress, so calling this method with a different buffer doesn't affect a search that's still in progress using another buffer.
queryBufferCall NavWorld.ContinueFindPath after this method to process the path search.
In the Editor, most invalid arguments throw an exception instead of producing a status. This applies to a NavWorld or a NavQueryBuffer that isn't valid, a or location whose node is no longer part of the NavMesh, start and end locations that belong to NavMeshes built for different agent types, and a array that doesn't have exactly 32 elements or that contains a value below .
Failurestartendcosts1.0fFor more information about area types and the traversal costs the search applies to them, refer to Areas and Costs.
Additional Resources: NavQueryStatus, NavMesh.GetAreaCost
Examples
using Unity.Collections;using UnityEngine;using Unity.AI.Navigation.LowLevel;public class FindPathExample : MonoBehaviour{ public Transform target; NavWorld m_World; NavQueryBuffer m_Buffer; void OnEnable() { m_World = NavWorld.GetDefaultWorld(); m_Buffer = new NavQueryBuffer(m_World, Allocator.Persistent, 1024); } void Update() { NavLocation start = m_World.MapLocation(transform.position, Vector3.one, 0); NavLocation end = m_World.MapLocation(target.position, Vector3.one, 0); if (!m_World.IsValid(start) || !m_World.IsValid(end)) return; NavQueryStatus status = m_World.BeginFindPath(m_Buffer, start, end); while ((status & NavQueryStatus.InProgress) != 0) status = m_World.ContinueFindPath(m_Buffer, 64, out int _); if ((status & NavQueryStatus.Success) == 0) return; status = m_World.EndFindPath(m_Buffer, out int pathSize); if ((status & NavQueryStatus.Success) == 0) return; NativeArray<NavNode> path = new NativeArray<NavNode>(pathSize, Allocator.Temp); int copied = m_World.GetResultFromFindPath(m_Buffer, path); // The path is a corridor of nodes, not a list of waypoints. Draw the gate that each // pair of consecutive nodes shares to see the corridor the agent can move through. for (int i = 0; i < copied - 1; i++) { if (m_World.GetPortalPoints(path[i], path[i + 1], out Vector3 left, out Vector3 right)) Debug.DrawLine(left, right, Color.yellow); } path.Dispose(); } void OnDisable() { m_Buffer.Dispose(); m_World.Dispose(); }}
using Unity.Collections;using UnityEngine;using UnityEngine.AI;using Unity.AI.Navigation.LowLevel;public class FindPathWithAreaCostsExample : MonoBehaviour{ // The navigation system defines exactly 32 area types and the costs array must match. const int k_AreaCount = 32; public Transform target; // Index of an area the agent should prefer to walk around, for example a "Water" area. public int avoidedArea = 4; public float avoidedAreaCost = 10f; NavWorld m_World; NavQueryBuffer m_Buffer; NativeArray<float> m_Costs; void OnEnable() { m_World = NavWorld.GetDefaultWorld(); m_Buffer = new NavQueryBuffer(m_World, Allocator.Persistent, 1024); // Start from the costs configured in the Navigation settings, then override one area. // Every entry must be at least 1, otherwise BeginFindPath throws an ArgumentException. m_Costs = new NativeArray<float>(k_AreaCount, Allocator.Persistent); for (int i = 0; i < k_AreaCount; i++) m_Costs[i] = Mathf.Max(1f, NavMesh.GetAreaCost(i)); m_Costs[avoidedArea] = Mathf.Max(1f, avoidedAreaCost); } void Update() { NavLocation start = m_World.MapLocation(transform.position, Vector3.one, 0); NavLocation end = m_World.MapLocation(target.position, Vector3.one, 0); if (!m_World.IsValid(start) || !m_World.IsValid(end)) return; // Costs only bias which route the search prefers; they never make an area impassable. // Clear the area's bit in the areaMask when you need to block it outright. NavQueryStatus status = m_World.BeginFindPath(m_Buffer, start, end, NavMesh.AllAreas, m_Costs); while ((status & NavQueryStatus.InProgress) != 0) status = m_World.ContinueFindPath(m_Buffer, 64, out int _); if ((status & NavQueryStatus.Success) == 0) return; status = m_World.EndFindPath(m_Buffer, out int pathSize); if ((status & NavQueryStatus.Success) == 0) return; if ((status & NavQueryStatus.PartialResult) != 0) Debug.Log($"Found a partial path of {pathSize} nodes that does not reach the target."); else Debug.Log($"Found a path of {pathSize} nodes that avoids area {avoidedArea}."); } void OnDisable() { m_Costs.Dispose(); m_Buffer.Dispose(); m_World.Dispose(); }}