using System.Collections.Generic; namespace UnityEngine.AI { [ExecuteInEditMode] [DefaultExecutionOrder(-101)] [AddComponentMenu("Navigation/NavMeshLink", 33)] [HelpURL("https://github.com/Unity-Technologies/NavMeshComponents#documentation-draft")] public class NavMeshLink : MonoBehaviour { [SerializeField] int m_AgentTypeID; public int agentTypeID { get { return m_AgentTypeID; } set { m_AgentTypeID = value; UpdateLink(); } } [SerializeField] Vector3 m_StartPoint = new Vector3(0.0f, 0.0f, -2.5f); public Vector3 startPoint { get { return m_StartPoint; } set { m_StartPoint = value; UpdateLink(); } } [SerializeField] Vector3 m_EndPoint = new Vector3(0.0f, 0.0f, 2.5f); public Vector3 endPoint { get { return m_EndPoint; } set { m_EndPoint = value; UpdateLink(); } } [SerializeField] float m_Width; public float width { get { return m_Width; } set { m_Width = value; UpdateLink(); } } [SerializeField] int m_CostModifier = -1; public int costModifier { get { return m_CostModifier; } set { m_CostModifier = value; UpdateLink(); } } [SerializeField] bool m_Bidirectional = true; public bool bidirectional { get { return m_Bidirectional; } set { m_Bidirectional = value; UpdateLink(); } } [SerializeField] bool m_AutoUpdatePosition; public bool autoUpdate { get { return m_AutoUpdatePosition; } set { SetAutoUpdate(value); } } [SerializeField] int m_Area; public int area { get { return m_Area; } set { m_Area = value; UpdateLink(); } } NavMeshLinkInstance m_LinkInstance = new NavMeshLinkInstance(); Vector3 m_LastPosition = Vector3.zero; Quaternion m_LastRotation = Quaternion.identity; static readonly List s_Tracked = new List(); void OnEnable() { AddLink(); if (m_AutoUpdatePosition && m_LinkInstance.valid) AddTracking(this); } void OnDisable() { RemoveTracking(this); m_LinkInstance.Remove(); } public void UpdateLink() { m_LinkInstance.Remove(); AddLink(); } static void AddTracking(NavMeshLink link) { #if UNITY_EDITOR if (s_Tracked.Contains(link)) { Debug.LogError("Link is already tracked: " + link); return; } #endif if (s_Tracked.Count == 0) NavMesh.onPreUpdate += UpdateTrackedInstances; s_Tracked.Add(link); } static void RemoveTracking(NavMeshLink link) { s_Tracked.Remove(link); if (s_Tracked.Count == 0) NavMesh.onPreUpdate -= UpdateTrackedInstances; } void SetAutoUpdate(bool value) { if (m_AutoUpdatePosition == value) return; m_AutoUpdatePosition = value; if (value) AddTracking(this); else RemoveTracking(this); } void AddLink() { #if UNITY_EDITOR if (m_LinkInstance.valid) { Debug.LogError("Link is already added: " + this); return; } #endif var link = new NavMeshLinkData(); link.startPosition = m_StartPoint; link.endPosition = m_EndPoint; link.width = m_Width; link.costModifier = m_CostModifier; link.bidirectional = m_Bidirectional; link.area = m_Area; link.agentTypeID = m_AgentTypeID; m_LinkInstance = NavMesh.AddLink(link, transform.position, transform.rotation); if (m_LinkInstance.valid) m_LinkInstance.owner = this; m_LastPosition = transform.position; m_LastRotation = transform.rotation; } bool HasTransformChanged() { if (m_LastPosition != transform.position) return true; if (m_LastRotation != transform.rotation) return true; return false; } void OnDidApplyAnimationProperties() { UpdateLink(); } static void UpdateTrackedInstances() { foreach (var instance in s_Tracked) { if (instance.HasTransformChanged()) instance.UpdateLink(); } } #if UNITY_EDITOR void OnValidate() { m_Width = Mathf.Max(0.0f, m_Width); if (!m_LinkInstance.valid) return; UpdateLink(); if (!m_AutoUpdatePosition) { RemoveTracking(this); } else if (!s_Tracked.Contains(this)) { AddTracking(this); } } #endif } }