Started project

This commit is contained in:
Caleb Sandford deQuincey
2025-11-14 17:30:41 +00:00
parent 00b55a5b1e
commit 334021d04e
36526 changed files with 4940113 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Unity.AI.Navigation.Tests")]

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3df4f0279114423485294ff1196c6644
timeCreated: 1697237057

View File

@@ -0,0 +1,16 @@
namespace Unity.AI.Navigation
{
/// <summary>
/// Helper for compile-time constant strings for the [HelpURL](xref:UnityEngine.HelpURLAttribute) attribute.
/// </summary>
static class HelpUrls
{
const string Version = "2.0";
const string BaseUrl = "https://docs.unity3d.com/Packages/com.unity.ai.navigation@" + Version;
internal const string Manual = BaseUrl + "/manual/";
internal const string Api = BaseUrl + "/api/";
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6ad3f38e8fe7c4058ad4c718b8774a9e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,619 @@
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.SceneManagement;
#endif
using UnityEngine;
using UnityEngine.AI;
#pragma warning disable IDE1006 // Unity-specific lower case public property names
namespace Unity.AI.Navigation
{
/// <summary> Component used to create a navigable link between two NavMesh locations. </summary>
[ExecuteAlways]
[DefaultExecutionOrder(-101)]
[AddComponentMenu("Navigation/NavMesh Link", 33)]
[HelpURL(HelpUrls.Manual + "NavMeshLink.html")]
public partial class NavMeshLink : MonoBehaviour
{
// Serialized version is used to upgrade older serialized data to the current format.
// Version 0: Initial version.
// Version 1: Added m_IsOverridingCost field and made m_CostModifier always positive.
[SerializeField, HideInInspector]
byte m_SerializedVersion = 0;
[SerializeField]
int m_AgentTypeID;
[SerializeField]
Vector3 m_StartPoint = new(0.0f, 0.0f, -2.5f);
[SerializeField]
Vector3 m_EndPoint = new(0.0f, 0.0f, 2.5f);
[SerializeField]
Transform m_StartTransform;
[SerializeField]
Transform m_EndTransform;
[SerializeField]
bool m_Activated = true;
[SerializeField]
float m_Width;
// This field's value in combination with m_IsOverridingCost determines the value of the costModifier property,
// where m_IsOverridingCost determines the sign of the value. The costModifier property is positive or zero when
// m_IsOverridingCost is true, and negative when m_IsOverridingCost is false.
// Note that when m_SerializedVersion >= 1, m_CostModifier will always become positive or zero. Newly created
// components are always upgraded to at least version 1 at initialization time.
[SerializeField]
[Min(0f)]
float m_CostModifier = -1f;
[SerializeField]
bool m_IsOverridingCost = false;
[SerializeField]
bool m_Bidirectional = true;
[SerializeField]
bool m_AutoUpdatePosition;
[SerializeField]
int m_Area;
#if UNITY_EDITOR
int m_LastArea;
#endif
/// <summary> Gets or sets the type of agent that can use the link. </summary>
public int agentTypeID
{
get => m_AgentTypeID;
set
{
if (value == m_AgentTypeID)
return;
m_AgentTypeID = value;
UpdateLink();
}
}
/// <summary> Gets or sets the local position at the middle of the link's start edge, relative to the GameObject origin. </summary>
/// <remarks> This property determines the position of the link's start edge only when <see cref="startTransform"/> is `null`. Otherwise, it is the `startTransform` that determines the edge's position. <br/>
/// The world scale of the GameObject is never used.</remarks>
public Vector3 startPoint
{
get => m_StartPoint;
set
{
if (value == m_StartPoint)
return;
m_StartPoint = value;
UpdateLink();
}
}
/// <summary> Gets or sets the local position at the middle of the link's end edge, relative to the GameObject origin. </summary>
/// <remarks> This property determines the position of the link's end edge only when <see cref="endTransform"/> is `null`. Otherwise, it is the `endTransform` that determines the edge's position. <br/>
/// The world scale of the GameObject is never used.</remarks>
public Vector3 endPoint
{
get => m_EndPoint;
set
{
if (value == m_EndPoint)
return;
m_EndPoint = value;
UpdateLink();
}
}
/// <summary> Gets or sets the <see cref="Transform"/> tracked by the middle of the link's start edge. </summary>
/// <remarks> The link places the start edge at the world position of the object referenced by this property. In that case <see cref="startPoint"/> is not used. Otherwise, when this property is `null`, the component applies the GameObject's translation and rotation as a transform to <see cref="startPoint"/> in order to establish the world position of the link's start edge. </remarks>
public Transform startTransform
{
get => m_StartTransform;
set
{
if (value == m_StartTransform)
return;
m_StartTransform = value;
UpdateLink();
}
}
/// <summary> Gets or sets the <see cref="Transform"/> tracked by the middle of the link's end edge. </summary>
/// <remarks> The link places the end edge at the world position of the object referenced by this property. In that case <see cref="endPoint"/> is not used. Otherwise, when this property is `null`, the component applies the GameObject's translation and rotation as a transform to <see cref="endPoint"/> in order to establish the world position of the link's end edge. </remarks>
public Transform endTransform
{
get => m_EndTransform;
set
{
if (value == m_EndTransform)
return;
m_EndTransform = value;
UpdateLink();
}
}
/// <summary> The width of the segments making up the ends of the link. </summary>
/// <remarks> The segments are created perpendicular to the line from start to end, in the XZ plane of the GameObject. </remarks>
public float width
{
get => m_Width;
set
{
if (value.Equals(m_Width))
return;
m_Width = value;
UpdateLink();
}
}
/// <summary> Gets or sets a value that determines the cost of traversing the link.</summary>
/// <remarks> A negative value implies that the cost of traversing the link is obtained based on the area type.<br/>
/// A positive or zero value overrides the cost associated with the area type.</remarks>
public float costModifier
{
get => m_IsOverridingCost ? m_CostModifier : -m_CostModifier;
set
{
var shouldOverride = value >= 0f;
if (value.Equals(costModifier) && shouldOverride == m_IsOverridingCost)
return;
m_IsOverridingCost = shouldOverride;
m_CostModifier = Mathf.Abs(value);
UpdateLink();
}
}
/// <summary> Gets or sets whether agents can traverse the link in both directions. </summary>
/// <remarks> When a link connects to NavMeshes at both ends, agents can always traverse that link from the start position to the end position. When this property is set to `true` it allows the agents to traverse the link from the end position to the start position as well. When the value is `false` the agents will not traverse the link from the end position to the start position. </remarks>
public bool bidirectional
{
get => m_Bidirectional;
set
{
if (value == m_Bidirectional)
return;
m_Bidirectional = value;
UpdateLink();
}
}
/// <summary> Gets or sets whether the world positions of the link's edges update whenever
/// the GameObject transform, the <see cref="startTransform"/> or the <see cref="endTransform"/> change at runtime. </summary>
public bool autoUpdate
{
get => m_AutoUpdatePosition;
set
{
if (value == m_AutoUpdatePosition)
return;
m_AutoUpdatePosition = value;
if (m_AutoUpdatePosition)
AddTracking(this);
else
RemoveTracking(this);
}
}
/// <summary> The area type of the link. </summary>
public int area
{
get => m_Area;
set
{
if (value == m_Area)
return;
m_Area = value;
UpdateLink();
}
}
/// <summary> Gets or sets whether the link can be traversed by agents. </summary>
/// <remarks> When this property is set to `true` it allows the agents to traverse the link. When the value is `false` no paths pass through this link and no agent can traverse it as part of their autonomous movement. </remarks>
public bool activated
{
get => m_Activated;
set
{
m_Activated = value;
NavMesh.SetLinkActive(m_LinkInstance, m_Activated);
}
}
/// <summary> Checks whether any agent occupies the link at this moment in time. </summary>
/// <remarks> This property evaluates the internal state of the link every time it is used. </remarks>
public bool occupied => NavMesh.IsLinkOccupied(m_LinkInstance);
NavMeshLinkInstance m_LinkInstance;
bool m_StartTransformWasEmpty = true;
bool m_EndTransformWasEmpty = true;
Vector3 m_LastStartWorldPosition = Vector3.positiveInfinity;
Vector3 m_LastEndWorldPosition = Vector3.positiveInfinity;
Vector3 m_LastPosition = Vector3.positiveInfinity;
Quaternion m_LastRotation = Quaternion.identity;
static readonly List<NavMeshLink> s_Tracked = new();
#if UNITY_EDITOR
bool m_DelayEndpointUpgrade;
static string s_LastWarnedPrefab;
static double s_NextPrefabWarningTime;
#endif
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void ClearTrackedList()
{
s_Tracked.Clear();
}
void UpgradeSerializedVersion()
{
if (m_SerializedVersion < 1)
{
#if UNITY_EDITOR
if (!StartEndpointUpgrade())
return;
#endif
m_SerializedVersion = 1;
m_IsOverridingCost = m_CostModifier >= 0f;
m_CostModifier = Mathf.Abs(m_CostModifier);
if (m_StartTransform == gameObject.transform)
m_StartTransform = null;
if (m_EndTransform == gameObject.transform)
m_EndTransform = null;
}
}
// ensures serialized version is up-to-date at run-time, in case it was not updated in the Editor
void Awake()
{
UpgradeSerializedVersion();
#if UNITY_EDITOR
m_LastArea = m_Area;
#endif
}
void OnEnable()
{
AddLink();
if (m_AutoUpdatePosition && NavMesh.IsLinkValid(m_LinkInstance))
AddTracking(this);
}
void OnDisable()
{
RemoveTracking(this);
NavMesh.RemoveLink(m_LinkInstance);
}
/// <summary> Replaces the link with a new one using the current settings. </summary>
public void UpdateLink()
{
if (!isActiveAndEnabled)
return;
NavMesh.RemoveLink(m_LinkInstance);
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);
link.RecordEndpointTransforms();
}
static void RemoveTracking(NavMeshLink link)
{
s_Tracked.Remove(link);
if (s_Tracked.Count == 0)
NavMesh.onPreUpdate -= UpdateTrackedInstances;
}
/// <summary>Gets the world positions of the start and end points for the link.</summary>
/// <param name="worldStartPosition">Returns the world position of <see cref="startTransform"/> if it is not <c>null</c>; otherwise, <see cref="startPoint"/> transformed into world space.</param>
/// <param name="worldEndPosition">Returns the world position of <see cref="endTransform"/> if it is not <c>null</c>; otherwise, <see cref="endPoint"/> transformed into world space.</param>
internal void GetWorldPositions(
out Vector3 worldStartPosition,
out Vector3 worldEndPosition)
{
var startIsLocal = m_StartTransform == null;
var endIsLocal = m_EndTransform == null;
var toWorld = startIsLocal || endIsLocal ? LocalToWorldUnscaled() : Matrix4x4.identity;
worldStartPosition = startIsLocal ? toWorld.MultiplyPoint3x4(m_StartPoint) : m_StartTransform.position;
worldEndPosition = endIsLocal ? toWorld.MultiplyPoint3x4(m_EndPoint) : m_EndTransform.position;
}
/// <summary>Gets the positions of the start and end points in the local space of the link.</summary>
/// <param name="localStartPosition">Returns the local position of <see cref="startTransform"/> if it is not <c>null</c>; otherwise, <see cref="startPoint"/>.</param>
/// <param name="localEndPosition">Returns the local position of <see cref="endTransform"/> if it is not <c>null</c>; otherwise, <see cref="endPoint"/>.</param>
internal void GetLocalPositions(
out Vector3 localStartPosition,
out Vector3 localEndPosition)
{
var startIsLocal = m_StartTransform == null;
var endIsLocal = m_EndTransform == null;
var toLocal = startIsLocal && endIsLocal ? Matrix4x4.identity : LocalToWorldUnscaled().inverse;
localStartPosition = startIsLocal ? m_StartPoint : toLocal.MultiplyPoint3x4(m_StartTransform.position);
localEndPosition = endIsLocal ? m_EndPoint : toLocal.MultiplyPoint3x4(m_EndTransform.position);
}
void AddLink()
{
#if UNITY_EDITOR
if (NavMesh.IsLinkValid(m_LinkInstance))
{
Debug.LogError("Link is already added: " + this);
return;
}
#endif
GetLocalPositions(out var localStartPosition, out var localEndPosition);
var link = new NavMeshLinkData
{
startPosition = localStartPosition,
endPosition = localEndPosition,
width = m_Width,
costModifier = costModifier,
bidirectional = m_Bidirectional,
area = m_Area,
agentTypeID = m_AgentTypeID,
};
m_LinkInstance = NavMesh.AddLink(link, transform.position, transform.rotation);
if (NavMesh.IsLinkValid(m_LinkInstance))
{
NavMesh.SetLinkOwner(m_LinkInstance, this);
NavMesh.SetLinkActive(m_LinkInstance, m_Activated);
}
m_LastPosition = transform.position;
m_LastRotation = transform.rotation;
#if UNITY_EDITOR
m_LastArea = m_Area;
#endif
RecordEndpointTransforms();
GetWorldPositions(out m_LastStartWorldPosition, out m_LastEndWorldPosition);
}
internal void RecordEndpointTransforms()
{
m_StartTransformWasEmpty = m_StartTransform == null;
m_EndTransformWasEmpty = m_EndTransform == null;
}
internal bool HaveTransformsChanged()
{
var startIsLocal = m_StartTransform == null;
var endIsLocal = m_EndTransform == null;
if (startIsLocal && endIsLocal &&
m_StartTransformWasEmpty && m_EndTransformWasEmpty &&
transform.position == m_LastPosition && transform.rotation == m_LastRotation)
return false;
var toWorld = startIsLocal || endIsLocal ? LocalToWorldUnscaled() : Matrix4x4.identity;
var startWorldPos = startIsLocal ? toWorld.MultiplyPoint3x4(m_StartPoint) : m_StartTransform.position;
if (startWorldPos != m_LastStartWorldPosition)
return true;
var endWorldPos = endIsLocal ? toWorld.MultiplyPoint3x4(m_EndPoint) : m_EndTransform.position;
return endWorldPos != m_LastEndWorldPosition;
}
internal Matrix4x4 LocalToWorldUnscaled()
{
return Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
}
void OnDidApplyAnimationProperties()
{
UpdateLink();
}
static void UpdateTrackedInstances()
{
foreach (var instance in s_Tracked)
{
if (instance.HaveTransformsChanged())
instance.UpdateLink();
instance.RecordEndpointTransforms();
}
}
#if UNITY_EDITOR
void OnValidate()
{
// Ensures serialized version is up-to-date in the Editor irrespective of GameObject active state
UpgradeSerializedVersion();
m_Width = Mathf.Max(0.0f, m_Width);
if (!NavMesh.IsLinkValid(m_LinkInstance) && (m_LastArea != 1 || m_Area == 1))
return;
UpdateLink();
if (!m_AutoUpdatePosition)
{
RemoveTracking(this);
}
else if (!s_Tracked.Contains(this))
{
AddTracking(this);
}
m_LastArea = m_Area;
}
void Reset()
{
UpgradeSerializedVersion();
}
bool StartEndpointUpgrade()
{
m_DelayEndpointUpgrade =
(m_StartTransform != null &&
m_StartTransform != gameObject.transform &&
m_StartPoint.sqrMagnitude > 0.0001f)
|| (m_EndTransform != null &&
m_EndTransform != gameObject.transform &&
m_EndPoint.sqrMagnitude > 0.0001f);
if (m_DelayEndpointUpgrade)
{
if (PrefabUtility.IsPartOfAnyPrefab(this))
{
var isInstance = PrefabUtility.IsPartOfPrefabInstance(this);
var prefabPath = isInstance
? PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(gameObject)
: AssetDatabase.GetAssetPath(gameObject);
if ((prefabPath != s_LastWarnedPrefab
|| EditorApplication.timeSinceStartup > s_NextPrefabWarningTime)
&& prefabPath != "")
{
var prefabToPing = AssetDatabase.LoadAssetAtPath<Object>(prefabPath);
Debug.LogWarning(L10n.Tr(
"A NavMesh Link component has an outdated format. "
+ "To upgrade it, open and save the prefab at: ") + prefabPath
+ (isInstance
? L10n.Tr(" . The prefab instance is ") + PrefabUtility.GetNearestPrefabInstanceRoot(gameObject).name
: ""),
prefabToPing);
s_LastWarnedPrefab = prefabPath;
s_NextPrefabWarningTime = EditorApplication.timeSinceStartup + 5f;
}
m_DelayEndpointUpgrade = false;
return false;
}
if (IsInAuthoringScene())
{
EditorApplication.delayCall += CompleteEndpointUpgrade;
EditorApplication.delayCall -= WarnAboutUnsavedUpgrade;
EditorApplication.delayCall += WarnAboutUnsavedUpgrade;
EditorSceneManager.MarkSceneDirty(gameObject.scene);
Debug.Log(L10n.Tr(
"A NavMesh Link component has auto-upgraded and it references a newly created object. "
+ "Save your scene to keep the changes. "
+ "GameObject: ") + gameObject.name,
gameObject);
}
else
{
Debug.LogWarning(L10n.Tr(
"The NavMesh Link component does not reference the intended transforms. " +
"To correct it, save this NavMesh Link again at edit time. GameObject: ") + gameObject.name,
gameObject);
}
}
return true;
}
static void WarnAboutUnsavedUpgrade()
{
Debug.LogWarning(L10n.Tr(
"At least one NavMesh Link component has auto-upgraded to a new format. "
+ "Save your scene to keep the changes. "));
}
void CompleteEndpointUpgrade()
{
var discardedByPrefabStageOnHiddenReload = this == null;
if (discardedByPrefabStageOnHiddenReload ||
gameObject == null || !m_DelayEndpointUpgrade)
return;
var linkIndexString = "";
var allMyLinks = gameObject.GetComponents<NavMeshLink>();
if (allMyLinks.Length > 1)
{
for (var i = 0; i < allMyLinks.Length; i++)
{
if (allMyLinks[i] == this)
{
linkIndexString = " " + i;
break;
}
}
}
var localToWorldUnscaled = LocalToWorldUnscaled();
if (m_StartTransform != null &&
m_StartTransform != gameObject.transform &&
m_StartPoint.sqrMagnitude > 0.0001f)
{
var startGO = new GameObject($"Link Start {gameObject.name}{linkIndexString}");
startGO.transform.SetParent(m_StartTransform);
startGO.transform.position = localToWorldUnscaled.MultiplyPoint3x4(transform.InverseTransformPoint(m_StartTransform.position + m_StartPoint));
m_StartTransform = startGO.transform;
}
if (m_EndTransform != null &&
m_EndTransform != gameObject.transform &&
m_EndPoint.sqrMagnitude > 0.0001f)
{
var endGO = new GameObject($"Link End {gameObject.name}{linkIndexString}");
endGO.transform.SetParent(m_EndTransform);
endGO.transform.position = localToWorldUnscaled.MultiplyPoint3x4(transform.InverseTransformPoint(m_EndTransform.position + m_EndPoint));
m_EndTransform = endGO.transform;
}
if (IsInAuthoringScene())
EditorSceneManager.MarkSceneDirty(gameObject.scene);
m_DelayEndpointUpgrade = false;
}
bool IsInAuthoringScene()
{
return !EditorApplication.isPlaying || PrefabStageUtility.GetPrefabStage(gameObject) != null;
}
#endif
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6eeb5dc026fdf4b488bc7ae0138ab719
timeCreated: 1477924439
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 92f4afa3e25264f5b964937ccea49ff2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
using System;
#pragma warning disable IDE1006 // Naming Styles
namespace Unity.AI.Navigation
{
public partial class NavMeshLink
{
/// <summary> Gets or sets whether the world positions of the link's edges update whenever
/// the GameObject transform, the start transform or the end transform change at runtime. </summary>
[Obsolete("autoUpdatePositions has been deprecated. Use autoUpdate instead. (UnityUpgradable) -> autoUpdate")]
public bool autoUpdatePositions
{
get => autoUpdate;
set => autoUpdate = value;
}
/// <summary> Gets or sets whether agents can traverse the link in both directions. </summary>
/// <remarks> When a link connects to NavMeshes at both ends, agents can always traverse that link from the start position to the end position. When this property is set to `true` it allows the agents to traverse the link from the end position to the start position as well. When the value is `false` the agents will not traverse the link from the end position to the start position. </remarks>
[Obsolete("biDirectional has been deprecated. Use bidirectional instead. (UnityUpgradable) -> bidirectional")]
public bool biDirectional
{
get => bidirectional;
set => bidirectional = value;
}
/// <summary> Gets or sets a value that determines the cost of traversing the link.</summary>
/// <remarks> A negative value implies that the cost of traversing the link is obtained based on the area type.
/// A positive or zero value overrides the cost associated with the area type.</remarks>
[Obsolete("costOverride has been deprecated. Use costModifier instead. (UnityUpgradable) -> costModifier")]
public float costOverride
{
get => costModifier;
set => costModifier = value;
}
/// <summary> Replaces the link with a new one using the current settings. </summary>
[Obsolete("UpdatePositions() has been deprecated. Use UpdateLink() instead. (UnityUpgradable) -> UpdateLink(*)")]
public void UpdatePositions()
{
UpdateLink();
}
}
}
#pragma warning restore IDE1006 // Naming Styles

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d4d7832a718690643968fd71bac1b029
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,134 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.AI;
namespace Unity.AI.Navigation
{
/// <summary> Component that modifies the properties of the GameObjects used for building a NavMesh. </summary>
/// <remarks>The properties apply to the current GameObject and can be optionally applied recursively to all its children
/// in the hierarchy. This modifier overrides the properties set to this GameObject by
/// any other NavMeshModifier in the parent hierarchy.</remarks>
[ExecuteAlways]
[DefaultExecutionOrder(-103)]
[AddComponentMenu("Navigation/NavMesh Modifier", 32)]
[HelpURL(HelpUrls.Manual + "NavMeshModifier.html")]
public class NavMeshModifier : MonoBehaviour
{
#pragma warning disable 0414
// Serialized version is used to upgrade older serialized data to the current format.
// Version 0: Initial version.
[SerializeField, HideInInspector]
byte m_SerializedVersion = 0;
#pragma warning restore 0414
[SerializeField]
bool m_OverrideArea;
[SerializeField]
int m_Area;
[SerializeField]
bool m_OverrideGenerateLinks;
[SerializeField]
bool m_GenerateLinks;
[SerializeField]
bool m_IgnoreFromBuild;
[SerializeField]
bool m_ApplyToChildren = true;
// List of agent types the modifier is applied for.
// Special values: empty == None, m_AffectedAgents[0] =-1 == All.
[SerializeField]
List<int> m_AffectedAgents = new List<int>(new int[] { -1 }); // Default value is All
/// <summary> Gets or sets whether to assign the <see cref="area"/> type to this object instead of the <see cref="NavMeshSurface.defaultArea"/>. </summary>
/// <remarks> The area type information is used when baking the NavMesh. </remarks>
/// <seealso href="https://docs.unity3d.com/Manual/nav-AreasAndCosts.html"/>
public bool overrideArea { get { return m_OverrideArea; } set { m_OverrideArea = value; } }
/// <summary> Gets or sets the area type applied by this GameObject. </summary>
/// <remarks> The range of useful values is from 0 to 31. Higher values always take precedence over lower values in the case when the surfaces of more GameObjects intersect each other to produce a NavMesh in the same region. A value of 1 has the highest priority over all the other types and it means "not walkable". Consequently, the surface of a GameObject with an <c>area</c> of 1 produces a hole in the NavMesh. This property has the same meaning as <see cref="NavMeshBuildSource.area"/>.</remarks>
/// <seealso href="https://docs.unity3d.com/Manual/nav-AreasAndCosts.html"/>
public int area { get { return m_Area; } set { m_Area = value; } }
/// <summary> Gets or sets whether the default links generation condition for the GameObject and its children should be overridden. </summary>
public bool overrideGenerateLinks { get { return m_OverrideGenerateLinks; } set { m_OverrideGenerateLinks = value; } }
/// <summary> Gets or sets whether this object is included in the link generation process. </summary>
public bool generateLinks { get { return m_GenerateLinks; } set { m_GenerateLinks = value; } }
/// <summary> Gets or sets whether the NavMesh building process ignores this GameObject and its children. </summary>
public bool ignoreFromBuild { get { return m_IgnoreFromBuild; } set { m_IgnoreFromBuild = value; } }
/// <summary> Gets or sets whether this GameObject's children also use the modifier settings. </summary>
public bool applyToChildren { get { return m_ApplyToChildren; } set { m_ApplyToChildren = value; } }
static bool s_RebuildNavMeshModifiers = true;
static List<NavMeshModifier> s_NavMeshModifiers = new List<NavMeshModifier>();
static readonly HashSet<NavMeshModifier> s_NavMeshModifiersSet = new HashSet<NavMeshModifier>();
/// <summary> Gets the list of all the <see cref="NavMeshModifier"/> components that are currently active in the scene. Copies the returned list from
/// an internal container and updates it whenever a NavMeshModifier is enabled or disabled. </summary>
public static List<NavMeshModifier> activeModifiers
{
get
{
if (s_RebuildNavMeshModifiers)
{
s_NavMeshModifiers = s_NavMeshModifiersSet.ToList();
s_RebuildNavMeshModifiers = false;
}
return s_NavMeshModifiers;
}
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void ClearNavMeshModifiers()
{
s_NavMeshModifiers.Clear();
s_NavMeshModifiersSet.Clear();
}
void OnEnable()
{
RegisterModifier();
}
void OnDisable()
{
UnregisterModifier();
}
void RegisterModifier()
{
if (s_NavMeshModifiersSet.Add(this))
{
s_RebuildNavMeshModifiers = true;
}
}
void UnregisterModifier()
{
if (s_NavMeshModifiersSet.Remove(this))
{
s_RebuildNavMeshModifiers = true;
}
}
/// <summary> Verifies whether this modifier can affect in any way the generation of a NavMesh for a given agent type. </summary>
/// <param name="agentTypeID"> The identifier of an agent type that originates from <see cref="NavMeshBuildSettings.agentTypeID"/>. </param>
/// <returns> <c>true</c> if this component can affect the NavMesh built for the given agent type; otherwise <c>false</c>. </returns>
public bool AffectsAgentType(int agentTypeID)
{
if (m_AffectedAgents.Count == 0)
return false;
if (m_AffectedAgents[0] == -1)
return true;
return m_AffectedAgents.IndexOf(agentTypeID) != -1;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1e3fdca004f2d45fe8abbed571a8abd5
timeCreated: 1477924411
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: b642c6bf23e624e23ad11b3e1d471932, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,84 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
namespace Unity.AI.Navigation
{
/// <summary> Component used by the NavMesh building process to assign a different area type to the region inside the specified volume.</summary>
[ExecuteAlways]
[AddComponentMenu("Navigation/NavMesh Modifier Volume", 31)]
[HelpURL(HelpUrls.Manual + "NavMeshModifierVolume.html")]
public class NavMeshModifierVolume : MonoBehaviour
{
#pragma warning disable 0414
// Serialized version is used to upgrade older serialized data to the current format.
// Version 0: Initial version.
[SerializeField, HideInInspector]
byte m_SerializedVersion = 0;
#pragma warning restore 0414
[SerializeField]
Vector3 m_Size = new Vector3(4.0f, 3.0f, 4.0f);
[SerializeField]
Vector3 m_Center = new Vector3(0, 1.0f, 0);
[SerializeField]
int m_Area;
/// <summary> Gets or sets the dimensions of the cuboid modifier volume. </summary>
/// <remarks> The dimensions apply in the local space of the GameObject. </remarks>
public Vector3 size { get { return m_Size; } set { m_Size = value; } }
/// <summary> Gets or sets the center position of the modifier volume. </summary>
/// <remarks> The position is relative to the GameObject transform. </remarks>
public Vector3 center { get { return m_Center; } set { m_Center = value; } }
/// <summary> Gets or sets the area type that will be enforced by the volume during the generation of the NavMesh. </summary>
/// <remarks> The range of useful values is from 0 to 31. Higher values always take precedence over lower values in the case when more volumes intersect each other. A value of 1 has the highest priority over all the other types and it means "not walkable". Consequently, a volume with an <c>area</c> of 1 produces a hole in the NavMesh. This property has the same meaning as <see cref="NavMeshBuildSource.area"/>.</remarks>
/// <seealso href="https://docs.unity3d.com/Manual/nav-AreasAndCosts.html"/>
public int area { get { return m_Area; } set { m_Area = value; } }
// List of agent types the modifier is applied for.
// Special values: empty == None, m_AffectedAgents[0] =-1 == All.
[SerializeField]
List<int> m_AffectedAgents = new List<int>(new int[] { -1 }); // Default value is All
static readonly List<NavMeshModifierVolume> s_NavMeshModifiers = new List<NavMeshModifierVolume>();
/// <summary> Gets the list of all the <see cref="NavMeshModifierVolume"/> components that are currently active in the scene. </summary>
public static List<NavMeshModifierVolume> activeModifiers
{
get { return s_NavMeshModifiers; }
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void ClearNavMeshModifiers()
{
s_NavMeshModifiers.Clear();
}
void OnEnable()
{
if (!s_NavMeshModifiers.Contains(this))
s_NavMeshModifiers.Add(this);
}
void OnDisable()
{
s_NavMeshModifiers.Remove(this);
}
/// <summary> Verifies whether this modifier volume can affect in any way the generation of a NavMesh for a given agent type. </summary>
/// <param name="agentTypeID"> The identifier of an agent type that originates from <see cref="NavMeshBuildSettings.agentTypeID"/>. </param>
/// <returns> <c>true</c> if this component can affect the NavMesh built for the given agent type; otherwise <c>false</c>. </returns>
public bool AffectsAgentType(int agentTypeID)
{
if (m_AffectedAgents.Count == 0)
return false;
if (m_AffectedAgents[0] == -1)
return true;
return m_AffectedAgents.IndexOf(agentTypeID) != -1;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 35e95dc5ff2b64380880dd7ac5922847
timeCreated: 1477924430
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: cc7b9475dbddf4f9088d327d6e10ab77, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,645 @@
using System.Collections.Generic;
#if UNITY_EDITOR
using System.Runtime.CompilerServices;
using UnityEditor;
using UnityEditor.SceneManagement;
#endif
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Serialization;
#if UNITY_EDITOR
[assembly: InternalsVisibleTo("Unity.AI.Navigation.Editor")]
#endif
namespace Unity.AI.Navigation
{
/// <summary> Sets the method for filtering the objects retrieved when baking the NavMesh. </summary>
public enum CollectObjects
{
/// <summary> Use all the active objects. </summary>
[InspectorName("All Game Objects")]
All = 0,
/// <summary> Use all the active objects that overlap the bounding volume. </summary>
[InspectorName("Volume")]
Volume = 1,
/// <summary> Use all the active objects that are children of this GameObject. </summary>
/// <remarks> This includes the current GameObject and all the children of the children that are active.</remarks>
[InspectorName("Current Object Hierarchy")]
Children = 2,
/// <summary> Use all the active objects that are marked with a NavMeshModifier. </summary>
[InspectorName("NavMeshModifier Component Only")]
MarkedWithModifier = 3,
}
/// <summary> Component used for building and enabling a NavMesh surface for one agent type. </summary>
[ExecuteAlways]
[DefaultExecutionOrder(-102)]
[AddComponentMenu("Navigation/NavMesh Surface", 30)]
[HelpURL(HelpUrls.Manual + "NavMeshSurface.html")]
public class NavMeshSurface : MonoBehaviour
{
#pragma warning disable 0414
// Serialized version is used to upgrade older serialized data to the current format.
// Version 0: Initial version.
[SerializeField, HideInInspector]
byte m_SerializedVersion = 0;
#pragma warning restore 0414
[SerializeField]
int m_AgentTypeID;
[SerializeField]
CollectObjects m_CollectObjects = CollectObjects.All;
[SerializeField]
Vector3 m_Size = new Vector3(10.0f, 10.0f, 10.0f);
[SerializeField]
Vector3 m_Center = new Vector3(0, 2.0f, 0);
[SerializeField]
LayerMask m_LayerMask = ~0;
[SerializeField]
NavMeshCollectGeometry m_UseGeometry = NavMeshCollectGeometry.RenderMeshes;
[SerializeField]
int m_DefaultArea;
[SerializeField]
bool m_GenerateLinks;
[SerializeField]
bool m_IgnoreNavMeshAgent = true;
[SerializeField]
bool m_IgnoreNavMeshObstacle = true;
[SerializeField]
bool m_OverrideTileSize;
[SerializeField]
int m_TileSize = 256;
[SerializeField]
bool m_OverrideVoxelSize;
[SerializeField]
float m_VoxelSize;
[SerializeField]
float m_MinRegionArea = 2;
[FormerlySerializedAs("m_BakedNavMeshData")]
[SerializeField]
NavMeshData m_NavMeshData;
[SerializeField]
bool m_BuildHeightMesh;
/// <summary> Gets or sets the identifier of the agent type that will use this NavMesh Surface. </summary>
public int agentTypeID { get { return m_AgentTypeID; } set { m_AgentTypeID = value; } }
/// <summary> Gets or sets the method for retrieving the objects that will be used for baking. </summary>
public CollectObjects collectObjects { get { return m_CollectObjects; } set { m_CollectObjects = value; } }
/// <summary> Gets or sets the size of the volume that delimits the NavMesh created by this component. </summary>
/// <remarks> It is used only when <c>collectObjects</c> is set to <c>Volume</c>. The size applies in the local space of the GameObject. </remarks>
public Vector3 size { get { return m_Size; } set { m_Size = value; } }
/// <summary> Gets or sets the center position of the volume that delimits the NavMesh created by this component. </summary>
/// <remarks> It is used only when <c>collectObjects</c> is set to <c>Volume</c>. The position applies in the local space of the GameObject. </remarks>
public Vector3 center { get { return m_Center; } set { m_Center = value; } }
/// <summary> Gets or sets a bitmask representing which layers to consider when selecting the objects that will be used for baking the NavMesh. </summary>
public LayerMask layerMask { get { return m_LayerMask; } set { m_LayerMask = value; } }
/// <summary> Gets or sets which type of component in the GameObjects provides the geometry used for baking the NavMesh. </summary>
public NavMeshCollectGeometry useGeometry { get { return m_UseGeometry; } set { m_UseGeometry = value; } }
/// <summary> Gets or sets the area type assigned to any object that does not have one specified. </summary>
/// <remarks> To customize the area type of an object add a <see cref="NavMeshModifier"/> component and set <see cref="NavMeshModifier.overrideArea"/> to <c>true</c>. The area type information is used when baking the NavMesh. </remarks>
/// <seealso href="https://docs.unity3d.com/Manual/nav-AreasAndCosts.html"/>
public int defaultArea { get { return m_DefaultArea; } set { m_DefaultArea = value; } }
/// <summary> Gets or sets whether the process of building the NavMesh ignores the GameObjects containing a <see cref="NavMeshAgent"/> component. </summary>
/// <remarks> There is generally no need for the NavMesh to take into consideration the objects that can move.</remarks>
public bool ignoreNavMeshAgent { get { return m_IgnoreNavMeshAgent; } set { m_IgnoreNavMeshAgent = value; } }
/// <summary> Gets or sets whether the process of building the NavMesh ignores the GameObjects containing a <see cref="NavMeshObstacle"/> component. </summary>
/// <remarks> There is generally no need for the NavMesh to take into consideration the objects that can move.</remarks>
public bool ignoreNavMeshObstacle { get { return m_IgnoreNavMeshObstacle; } set { m_IgnoreNavMeshObstacle = value; } }
/// <summary> Gets or sets whether the NavMesh building process uses the <see cref="tileSize"/> value. </summary>
public bool overrideTileSize { get { return m_OverrideTileSize; } set { m_OverrideTileSize = value; } }
/// <summary> Gets or sets the width of the square grid of voxels that the NavMesh building process uses for sampling the scene geometry. </summary>
/// <remarks> This value represents a number of voxels. Together with <see cref="voxelSize"/> it determines the real size of the individual sections that comprise the NavMesh. </remarks>
public int tileSize { get { return m_TileSize; } set { m_TileSize = value; } }
/// <summary> Gets or sets whether the NavMesh building process uses the <see cref="voxelSize"/> value. </summary>
public bool overrideVoxelSize { get { return m_OverrideVoxelSize; } set { m_OverrideVoxelSize = value; } }
/// <summary> Gets or sets the width of the square voxels that the NavMesh building process uses for sampling the scene geometry. </summary>
/// <remarks> This value is in world units. Together with <see cref="tileSize"/> it determines the real size of the individual sections that comprise the NavMesh. </remarks>
public float voxelSize { get { return m_VoxelSize; } set { m_VoxelSize = value; } }
/// <summary> Gets or sets the minimum acceptable surface area of any continuous portion of the NavMesh. </summary>
/// <remarks> This parameter is used only at the time when the NavMesh is getting built. It allows you to cull away any isolated NavMesh regions that are smaller than this value and that do not straddle or touch a tile boundary. </remarks>
public float minRegionArea { get { return m_MinRegionArea; } set { m_MinRegionArea = value; } }
/// <summary> Gets or sets whether the NavMesh building process produces more detailed elevation information. </summary>
/// <seealso href="https://docs.unity3d.com/Packages/com.unity.ai.navigation@1.0/manual/NavMeshSurface.html#advanced-settings"/>
public bool buildHeightMesh { get { return m_BuildHeightMesh; } set { m_BuildHeightMesh = value; } }
/// <summary> Gets or sets the reference to the NavMesh data instantiated by this surface. </summary>
public NavMeshData navMeshData { get { return m_NavMeshData; } set { m_NavMeshData = value; } }
// Do not serialize - runtime only state.
NavMeshDataInstance m_NavMeshDataInstance;
Vector3 m_LastPosition = Vector3.zero;
Quaternion m_LastRotation = Quaternion.identity;
internal NavMeshDataInstance navMeshDataInstance => m_NavMeshDataInstance;
static readonly List<NavMeshSurface> s_NavMeshSurfaces = new List<NavMeshSurface>();
/// <summary> Gets the list of all the <see cref="NavMeshSurface"/> components that are currently active in the scene. </summary>
public static List<NavMeshSurface> activeSurfaces
{
get { return s_NavMeshSurfaces; }
}
Bounds GetInflatedBounds()
{
var settings = NavMesh.GetSettingsByID(m_AgentTypeID);
var agentRadius = settings.agentTypeID != -1 ? settings.agentRadius : 0f;
var bounds = new Bounds(center, size);
bounds.Expand(new Vector3(agentRadius, 0, agentRadius));
return bounds;
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void ClearNavMeshSurfaces()
{
s_NavMeshSurfaces.Clear();
}
void OnEnable()
{
Register(this);
AddData();
}
void OnDisable()
{
RemoveData();
Unregister(this);
}
/// <summary> Creates an instance of the NavMesh data and activates it in the navigation system. </summary>
/// <remarks> The instance is created at the position and with the orientation of the GameObject. </remarks>
public void AddData()
{
#if UNITY_EDITOR
if (IsEditedInPrefab(this))
return;
#endif
if (m_NavMeshDataInstance.valid)
return;
if (m_NavMeshData != null)
{
m_NavMeshDataInstance = NavMesh.AddNavMeshData(m_NavMeshData, transform.position, transform.rotation);
m_NavMeshDataInstance.owner = this;
}
m_LastPosition = transform.position;
m_LastRotation = transform.rotation;
}
/// <summary> Removes the instance of this NavMesh data from the navigation system. </summary>
/// <remarks> This operation does not destroy the <see cref="navMeshData"/>. </remarks>
public void RemoveData()
{
m_NavMeshDataInstance.Remove();
m_NavMeshDataInstance = new NavMeshDataInstance();
}
/// <summary> Retrieves a copy of the current settings chosen for building this NavMesh surface. </summary>
/// <returns> The settings configured in this NavMeshSurface. </returns>
public NavMeshBuildSettings GetBuildSettings()
{
var buildSettings = NavMesh.GetSettingsByID(m_AgentTypeID);
if (buildSettings.agentTypeID == -1)
{
Debug.LogWarning("No build settings for agent type ID " + agentTypeID, this);
buildSettings.agentTypeID = m_AgentTypeID;
}
if (overrideTileSize)
{
buildSettings.overrideTileSize = true;
buildSettings.tileSize = tileSize;
}
if (overrideVoxelSize)
{
buildSettings.overrideVoxelSize = true;
buildSettings.voxelSize = voxelSize;
}
buildSettings.minRegionArea = minRegionArea;
buildSettings.buildHeightMesh = buildHeightMesh;
return buildSettings;
}
/// <summary> Builds and instantiates this NavMesh surface. </summary>
public void BuildNavMesh()
{
var sources = CollectSources();
// Use unscaled bounds - this differs in behaviour from e.g. collider components.
// But is similar to reflection probe - and since NavMesh data has no scaling support - it is the right choice here.
var surfaceBounds = new Bounds(m_Center, Abs(m_Size));
if (m_CollectObjects != CollectObjects.Volume)
{
surfaceBounds = CalculateWorldBounds(sources);
}
var data = NavMeshBuilder.BuildNavMeshData(GetBuildSettings(),
sources, surfaceBounds, transform.position, transform.rotation);
if (data != null)
{
data.name = gameObject.name;
RemoveData();
m_NavMeshData = data;
if (isActiveAndEnabled)
AddData();
}
}
/// <summary> Rebuilds parts of an existing NavMesh in the regions of the scene where the objects have changed. </summary>
/// <remarks> This operation is executed asynchronously. </remarks>
/// <param name="data"> The NavMesh to update according to the changes in the scene. </param>
/// <returns> A reference to the asynchronous coroutine that builds the NavMesh. </returns>
public AsyncOperation UpdateNavMesh(NavMeshData data)
{
var sources = CollectSources();
// Use unscaled bounds - this differs in behaviour from e.g. collider components.
// But is similar to reflection probe - and since NavMesh data has no scaling support - it is the right choice here.
var surfaceBounds = new Bounds(m_Center, Abs(m_Size));
if (m_CollectObjects != CollectObjects.Volume)
surfaceBounds = CalculateWorldBounds(sources);
return NavMeshBuilder.UpdateNavMeshDataAsync(data, GetBuildSettings(), sources, surfaceBounds);
}
static void Register(NavMeshSurface surface)
{
#if UNITY_EDITOR
if (IsEditedInPrefab(surface))
return;
#endif
if (s_NavMeshSurfaces.Count == 0)
NavMesh.onPreUpdate += UpdateActive;
if (!s_NavMeshSurfaces.Contains(surface))
s_NavMeshSurfaces.Add(surface);
}
static void Unregister(NavMeshSurface surface)
{
s_NavMeshSurfaces.Remove(surface);
if (s_NavMeshSurfaces.Count == 0)
NavMesh.onPreUpdate -= UpdateActive;
}
static void UpdateActive()
{
for (var i = 0; i < s_NavMeshSurfaces.Count; ++i)
s_NavMeshSurfaces[i].UpdateDataIfTransformChanged();
}
void AppendModifierVolumes(ref List<NavMeshBuildSource> sources)
{
#if UNITY_EDITOR
var myStage = StageUtility.GetStageHandle(gameObject);
if (!myStage.IsValid())
return;
#endif
// Modifiers
List<NavMeshModifierVolume> modifiers;
if (m_CollectObjects == CollectObjects.Children)
{
modifiers = new List<NavMeshModifierVolume>(GetComponentsInChildren<NavMeshModifierVolume>());
modifiers.RemoveAll(x => !x.isActiveAndEnabled);
}
else
{
modifiers = NavMeshModifierVolume.activeModifiers;
}
foreach (var m in modifiers)
{
if ((m_LayerMask & (1 << m.gameObject.layer)) == 0)
continue;
if (!m.AffectsAgentType(m_AgentTypeID))
continue;
#if UNITY_EDITOR
if (!myStage.Contains(m.gameObject))
continue;
#endif
var mcenter = m.transform.TransformPoint(m.center);
var scale = m.transform.lossyScale;
var msize = new Vector3(m.size.x * Mathf.Abs(scale.x), m.size.y * Mathf.Abs(scale.y), m.size.z * Mathf.Abs(scale.z));
var src = new NavMeshBuildSource();
src.shape = NavMeshBuildSourceShape.ModifierBox;
src.transform = Matrix4x4.TRS(mcenter, m.transform.rotation, Vector3.one);
src.size = msize;
src.area = m.area;
sources.Add(src);
}
}
List<NavMeshBuildSource> CollectSources()
{
var sources = new List<NavMeshBuildSource>();
var markups = new List<NavMeshBuildMarkup>();
List<NavMeshModifier> modifiers;
if (m_CollectObjects == CollectObjects.Children)
{
modifiers = new List<NavMeshModifier>(GetComponentsInChildren<NavMeshModifier>());
modifiers.RemoveAll(x => !x.isActiveAndEnabled);
}
else
{
modifiers = NavMeshModifier.activeModifiers;
}
foreach (var m in modifiers)
{
if ((m_LayerMask & (1 << m.gameObject.layer)) == 0)
continue;
if (!m.AffectsAgentType(m_AgentTypeID))
continue;
var markup = new NavMeshBuildMarkup();
markup.root = m.transform;
markup.overrideArea = m.overrideArea;
markup.area = m.area;
markup.ignoreFromBuild = m.ignoreFromBuild;
markup.applyToChildren = m.applyToChildren;
markup.overrideGenerateLinks = m.overrideGenerateLinks;
markup.generateLinks = m.generateLinks;
markups.Add(markup);
}
switch (m_CollectObjects)
{
default:
case CollectObjects.All:
CollectSourcesInHierarchy(null, m_LayerMask, m_UseGeometry, m_DefaultArea, m_GenerateLinks, markups, false, sources);
break;
case CollectObjects.Children:
CollectSourcesInHierarchy(transform, m_LayerMask, m_UseGeometry, m_DefaultArea, m_GenerateLinks, markups, false, sources);
break;
case CollectObjects.Volume:
{
var localToWorld = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
var worldBounds = GetWorldBounds(localToWorld, GetInflatedBounds());
CollectSourcesInVolume(worldBounds, m_LayerMask, m_UseGeometry, m_DefaultArea, m_GenerateLinks, markups, false, sources);
break;
}
case CollectObjects.MarkedWithModifier:
CollectSourcesInHierarchy(null, m_LayerMask, m_UseGeometry, m_DefaultArea, m_GenerateLinks, markups, true, sources);
break;
}
if (m_IgnoreNavMeshAgent)
sources.RemoveAll((x) => (x.component != null && x.component.gameObject.GetComponent<NavMeshAgent>() != null));
if (m_IgnoreNavMeshObstacle)
sources.RemoveAll((x) => (x.component != null && x.component.gameObject.GetComponent<NavMeshObstacle>() != null));
AppendModifierVolumes(ref sources);
return sources;
}
static Vector3 Abs(Vector3 v)
{
return new Vector3(Mathf.Abs(v.x), Mathf.Abs(v.y), Mathf.Abs(v.z));
}
static Bounds GetWorldBounds(Matrix4x4 mat, Bounds bounds)
{
var absAxisX = Abs(mat.MultiplyVector(Vector3.right));
var absAxisY = Abs(mat.MultiplyVector(Vector3.up));
var absAxisZ = Abs(mat.MultiplyVector(Vector3.forward));
var worldPosition = mat.MultiplyPoint(bounds.center);
var worldSize = absAxisX * bounds.size.x + absAxisY * bounds.size.y + absAxisZ * bounds.size.z;
return new Bounds(worldPosition, worldSize);
}
Bounds CalculateWorldBounds(List<NavMeshBuildSource> sources)
{
// Use the unscaled matrix for the NavMeshSurface
Matrix4x4 worldToLocal = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
worldToLocal = worldToLocal.inverse;
var result = new Bounds();
foreach (var src in sources)
{
switch (src.shape)
{
case NavMeshBuildSourceShape.Mesh:
{
var m = src.sourceObject as Mesh;
result.Encapsulate(GetWorldBounds(worldToLocal * src.transform, m.bounds));
break;
}
case NavMeshBuildSourceShape.Terrain:
{
#if NMC_CAN_ACCESS_TERRAIN
// Terrain pivot is lower/left corner - shift bounds accordingly
var t = src.sourceObject as TerrainData;
result.Encapsulate(GetWorldBounds(worldToLocal * src.transform, new Bounds(0.5f * t.size, t.size)));
#else
Debug.LogWarning("The NavMesh cannot be properly baked for the terrain because the necessary functionality is missing. Add the com.unity.modules.terrain package through the Package Manager.");
#endif
break;
}
case NavMeshBuildSourceShape.Box:
case NavMeshBuildSourceShape.Sphere:
case NavMeshBuildSourceShape.Capsule:
case NavMeshBuildSourceShape.ModifierBox:
result.Encapsulate(GetWorldBounds(worldToLocal * src.transform, new Bounds(Vector3.zero, src.size)));
break;
}
}
// Inflate the bounds a bit to avoid clipping co-planar sources
result.Expand(0.1f);
return result;
}
bool HasTransformChanged()
{
if (m_LastPosition != transform.position)
return true;
if (m_LastRotation != transform.rotation)
return true;
return false;
}
void UpdateDataIfTransformChanged()
{
if (HasTransformChanged())
{
RemoveData();
AddData();
}
}
void CollectSourcesInVolume(
Bounds includedWorldBounds, int includedLayerMask, NavMeshCollectGeometry geometry, int areaByDefault, bool generateLinksByDefault,
List<NavMeshBuildMarkup> markups, bool includeOnlyMarkedObjects, List<NavMeshBuildSource> results)
{
#if UNITY_EDITOR
if (!EditorApplication.isPlaying || IsPartOfPrefab())
{
#if EDITOR_ONLY_NAVMESH_BUILDER_DEPRECATED
UnityEditor.AI.NavMeshEditorHelpers.CollectSourcesInStage(
includedWorldBounds, includedLayerMask, geometry, areaByDefault, generateLinksByDefault,
markups, includeOnlyMarkedObjects, gameObject.scene, results);
#else
UnityEditor.AI.NavMeshBuilder.CollectSourcesInStage(
includedWorldBounds, includedLayerMask, geometry, areaByDefault, generateLinksByDefault,
markups, includeOnlyMarkedObjects, gameObject.scene, results);
#endif
}
else
#endif
{
NavMeshBuilder.CollectSources(
includedWorldBounds, includedLayerMask, geometry, areaByDefault, generateLinksByDefault,
markups, includeOnlyMarkedObjects, results);
}
}
void CollectSourcesInHierarchy(
Transform root, int includedLayerMask, NavMeshCollectGeometry geometry, int areaByDefault, bool generateLinksByDefault,
List<NavMeshBuildMarkup> markups, bool includeOnlyMarkedObjects, List<NavMeshBuildSource> results)
{
#if UNITY_EDITOR
if (!EditorApplication.isPlaying || IsPartOfPrefab())
{
#if EDITOR_ONLY_NAVMESH_BUILDER_DEPRECATED
UnityEditor.AI.NavMeshEditorHelpers.CollectSourcesInStage(
root, includedLayerMask, geometry, areaByDefault, generateLinksByDefault,
markups, includeOnlyMarkedObjects, gameObject.scene, results);
#else
UnityEditor.AI.NavMeshBuilder.CollectSourcesInStage(
root, includedLayerMask, geometry, areaByDefault, generateLinksByDefault,
markups, includeOnlyMarkedObjects, gameObject.scene, results);
#endif
}
else
#endif
{
NavMeshBuilder.CollectSources(
root, includedLayerMask, geometry, areaByDefault, generateLinksByDefault,
markups, includeOnlyMarkedObjects, results);
}
}
#if UNITY_EDITOR
bool UnshareNavMeshAsset()
{
// Nothing to unshare
if (m_NavMeshData == null)
return false;
// Prefab parent owns the asset reference
var isInPreviewScene = EditorSceneManager.IsPreviewSceneObject(this);
var isPersistentObject = EditorUtility.IsPersistent(this);
if (isInPreviewScene || isPersistentObject)
return false;
// An instance can share asset reference only with its prefab parent
var prefab = PrefabUtility.GetCorrespondingObjectFromSource(this) as NavMeshSurface;
if (prefab != null && prefab.navMeshData == navMeshData)
return false;
// Don't allow referencing an asset that's assigned to another surface
for (var i = 0; i < s_NavMeshSurfaces.Count; ++i)
{
var surface = s_NavMeshSurfaces[i];
if (surface != this && surface.m_NavMeshData == m_NavMeshData)
return true;
}
// Asset is not referenced by known surfaces
return false;
}
void OnValidate()
{
if (UnshareNavMeshAsset())
{
Debug.LogWarning("Duplicating NavMeshSurface does not duplicate the referenced NavMesh data", this);
m_NavMeshData = null;
}
var settings = NavMesh.GetSettingsByID(m_AgentTypeID);
if (settings.agentTypeID != -1)
{
// When unchecking the override control, revert to automatic value.
const float kMinVoxelSize = 0.01f;
if (!m_OverrideVoxelSize)
m_VoxelSize = settings.agentRadius / 3.0f;
if (m_VoxelSize < kMinVoxelSize)
m_VoxelSize = kMinVoxelSize;
// When unchecking the override control, revert to default value.
const int kMinTileSize = 16;
const int kMaxTileSize = 1024;
const int kDefaultTileSize = 256;
if (!m_OverrideTileSize)
m_TileSize = kDefaultTileSize;
// Make sure tilesize is in sane range.
if (m_TileSize < kMinTileSize)
m_TileSize = kMinTileSize;
if (m_TileSize > kMaxTileSize)
m_TileSize = kMaxTileSize;
if (m_MinRegionArea < 0)
m_MinRegionArea = 0;
}
}
static bool IsEditedInPrefab(NavMeshSurface navMeshSurface)
{
var isInPreviewScene = EditorSceneManager.IsPreviewSceneObject(navMeshSurface);
var isPrefab = isInPreviewScene || EditorUtility.IsPersistent(navMeshSurface);
// if (isPrefab)
// Debug.Log($"NavMeshData from {navMeshSurface.gameObject.name}.{navMeshSurface.name} will not be added to the NavMesh world because the gameObject is a prefab.");
return isPrefab;
}
internal bool IsPartOfPrefab()
{
var prefabStage = PrefabStageUtility.GetPrefabStage(gameObject);
var isPartOfPrefab = prefabStage != null && prefabStage.IsPartOfPrefabContents(gameObject);
return isPartOfPrefab;
}
#endif
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 7a5ac11cc976e418e8d13136b07e1f52
timeCreated: 1477658803
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: e4f97225bcfb64760a1c81f460837f01, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
{
"name": "Unity.AI.Navigation",
"rootNamespace": "",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.modules.terrain",
"expression": "1.0.0",
"define": "NMC_CAN_ACCESS_TERRAIN"
}
],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8c4dd21966739024fbd72155091d199e
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: