Version: Unity 6.5 (6000.5)
LanguageEnglish
  • C#

NavWorld.GetLinkNode

Suggest a change

Success!

Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable.

Close

Submission failed

For some reason your suggested change could not be submitted. Please <a>try again</a> in a few minutes. And thank you for taking the time to help us improve the quality of Unity Documentation.

Close

Cancel

Declaration

public NavNode GetLinkNode(NavMeshLinkInstance linkInstance);

Parameters

Parameter Description
linkInstance The object that identifies a navigation link created between locations on one or more NavMeshes.

Returns

NavNode The identifier of the node that represents the link in the navigation system.

Description

Retrieves the navigation node of a link that connects to one or more NavMeshes.

The resulting link identifier is valid for any link instance that is valid. This is true even if the link doesn't connect to any NavMeshes, or if the link is deactivated with NavMesh.SetLinkActive. A link instance preserves its unique identifier for the entire duration of the game, regardless of whether it connects to new NavMeshes or it disconnects from existing ones. The link identifier becomes invalid when the link is removed from the navigation system, or when all data of the navigation system is removed.

Note: You can't change the properties of an existing link instance. However, you can remove the existing instance and then replace it with one that has the modified properties.

Note: The navigation system doesn't provide a way to retrieve the NavMeshLinkInstance that corresponds to a NavNode. You need to address that use case yourself. For example, you can store link instance and identifier pairs in a list or dictionary, which you can then search when needed.

Additional resources: NavMesh.AddLink, NavWorld.GetEdgesAndNeighbors

using System;
using Unity.AI.Navigation.LowLevel;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine;
using UnityEngine.AI;

/// <summary>
/// This component creates a NavMesh Link between two points in the scene.
/// It logs in the Console the number of NavMesh polygons the Link connects to.
/// </summary>
public class ShowNavMeshLinkConnectivityInfo : MonoBehaviour
{
    public Vector3 linkLocalStart = new(-1f, 0f, 0f);
    public Vector3 linkLocalEnd = new(1f, 0f, 0f);
    public float linkWidth = 0.5f;
    public int connectionsAtStart;
    public int connectionsAtEnd;

    NavWorld m_NavWorld;
    NativeArray<NavMeshLinkInstance> m_LinkInstances;
    NativeArray<NavNode> m_LinkNodes;
    NativeArray<byte> m_EdgeIndexToNeighbor;

    struct GetLinkIdJob : IJobFor
    {
        [ReadOnly] public NavWorld world;
        [ReadOnly] public NativeArray<NavMeshLinkInstance> linkInstances;
        public NativeArray<NavNode> linkNodes;

        public void Execute(int i)
        {
            linkNodes[i] = world.GetLinkNode(linkInstances[i]);
        }
    }

    void Awake()
    {
        m_NavWorld = NavWorld.GetDefaultWorld();
        m_LinkInstances = new NativeArray<NavMeshLinkInstance>(1, Allocator.Persistent);
        m_LinkNodes = new NativeArray<NavNode>(1, Allocator.Persistent);
        m_EdgeIndexToNeighbor = new NativeArray<byte>(20, Allocator.Persistent);
    }

    void RefreshLink()
    {
        if (NavMesh.IsLinkValid(m_LinkInstances[0]))
            NavMesh.RemoveLink(m_LinkInstances[0]);

        m_LinkInstances[0] = NavMesh.AddLink(
            new NavMeshLinkData
            {
                startPosition = linkLocalStart,
                endPosition = linkLocalEnd,
                width = linkWidth,
                agentTypeID = 0
            },
            transform.position,
            transform.rotation);
    }

    void Update()
    {
        RefreshLink();

        GetLinkIdJob getLinkIdJob = new GetLinkIdJob
        {
            world = m_NavWorld,
            linkInstances = m_LinkInstances,
            linkNodes = m_LinkNodes
        };

        JobHandle jobHandle = getLinkIdJob.Schedule(m_LinkInstances.Length, default);
        m_NavWorld.AddDependency(jobHandle);
        JobHandle.ScheduleBatchedJobs();
        jobHandle.Complete();

        NavQueryStatus queryStatus = m_NavWorld.GetEdgesAndNeighbors(
            m_LinkNodes[0], default, default, m_EdgeIndexToNeighbor,
            out _, out int neighborsCount);

        if ((queryStatus & NavQueryStatus.Success) == NavQueryStatus.Success)
        {
            int indicesCount = Math.Min(m_EdgeIndexToNeighbor.Length, neighborsCount);

            int nStartPolygons = 0;
            for (int i = 0; i < indicesCount; i++)
            {
                if (m_EdgeIndexToNeighbor[i] == 0)
                    nStartPolygons++;
            }

            int nEndPolygons = neighborsCount - nStartPolygons;

            if (connectionsAtStart != nStartPolygons || connectionsAtEnd != nEndPolygons)
                Debug.Log($"Link starts in {nStartPolygons} polygons and ends in {nEndPolygons} polygons.");

            connectionsAtStart = nStartPolygons;
            connectionsAtEnd = nEndPolygons;
        }
    }

    void OnDisable()
    {
        NavMesh.RemoveLink(m_LinkInstances[0]);
        connectionsAtStart = 0;
        connectionsAtEnd = 0;
    }

    void OnDestroy()
    {
        m_LinkInstances.Dispose();
        m_LinkNodes.Dispose();
        m_EdgeIndexToNeighbor.Dispose();
        m_NavWorld.Dispose();
    }
}