first commit

This commit is contained in:
lethanhsonvsp
2025-11-17 15:36:52 +07:00
commit 6f2eafa33c
14093 changed files with 1253472 additions and 0 deletions

View File

@@ -0,0 +1,252 @@
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools.Utils;
namespace Unity.AI.Navigation.Tests
{
public class NavMeshLinkTests
{
NavMeshLink m_NavMeshLink;
Transform m_StartTransform;
Transform m_EndTransform;
GameObject m_ScaledSkewer;
GameObject m_LinkImitator;
GameObject m_LinkStartImitator;
GameObject m_LinkEndImitator;
[OneTimeSetUp]
public void OneTimeSetUp()
{
m_NavMeshLink = new GameObject("NavMeshLink").AddComponent<NavMeshLink>();
m_StartTransform = new GameObject("Start Transform").transform;
m_EndTransform = new GameObject("End Transform").transform;
m_ScaledSkewer = new GameObject("Unevenly Scaled Skewer");
m_LinkImitator = new GameObject("Link Imitator");
m_LinkStartImitator = new GameObject("Link Start Imitator");
m_LinkEndImitator = new GameObject("Link End Imitator");
Assume.That(k_UnevenScale / k_UnevenScale.x, Is.Not.EqualTo(Vector3.one).Using(Vector3EqualityComparer.Instance));
m_ScaledSkewer.transform.localScale = k_UnevenScale;
m_ScaledSkewer.transform.SetPositionAndRotation(new Vector3(2f, 1f, 1f), Quaternion.identity);
m_LinkImitator.transform.parent = m_ScaledSkewer.transform;
m_LinkStartImitator.transform.parent = m_LinkImitator.transform;
m_LinkEndImitator.transform.parent = m_LinkImitator.transform;
// To debug, add these components to imitators, only to show icons for them in the scene
//m_LinkStartImitator.AddComponent<NavMeshModifier>().enabled = false;
//m_LinkEndImitator.AddComponent<NavMeshModifier>().enabled = false;
//m_ScaledSkewer.AddComponent<NavMeshModifierVolume>().enabled = false;
}
[SetUp]
public void SetUp()
{
m_NavMeshLink.transform.parent = null;
// Note: Adjust the expected test return values if you change the setup
m_NavMeshLink.startPoint = Vector3.back;
m_NavMeshLink.endPoint = Vector3.forward;
m_StartTransform.position = Vector3.left;
m_EndTransform.position = Vector3.right;
}
[OneTimeTearDown]
public void OneTimeTearDown()
{
if (m_NavMeshLink != null)
Object.DestroyImmediate(m_NavMeshLink.gameObject);
if (m_StartTransform != null)
Object.DestroyImmediate(m_StartTransform.gameObject);
if (m_EndTransform != null)
Object.DestroyImmediate(m_EndTransform.gameObject);
if (m_LinkStartImitator != null)
Object.DestroyImmediate(m_LinkStartImitator);
if (m_LinkEndImitator != null)
Object.DestroyImmediate(m_LinkEndImitator);
if (m_LinkImitator != null)
Object.DestroyImmediate(m_LinkImitator);
if (m_ScaledSkewer != null)
Object.DestroyImmediate(m_ScaledSkewer);
}
static readonly Quaternion k_RotatedAroundYAxis = new(0f, 1f, 0f, 0f);
static readonly Quaternion k_ArbitraryRotationAroundYAxis = Quaternion.Euler(0f, 25f, 0f);
static readonly Vector3 k_UniformScale = new(2f, 2f, 2f);
static readonly Vector3 k_UnevenScale = new(2f, 1f, 0.7f);
static readonly TestCaseData[] k_TestCases =
{
new TestCaseData(Vector3.zero, Quaternion.identity, Vector3.one, false, false)
.SetName("At origin, use start and end points")
.Returns((Vector3.back, Vector3.forward)),
new TestCaseData(Vector3.zero, Quaternion.identity, Vector3.one, false, true)
.SetName("At origin, use start point and end transform")
.Returns((Vector3.back, Vector3.right)),
new TestCaseData(Vector3.zero, Quaternion.identity, Vector3.one, true, false)
.SetName("At origin, use start transform and end point")
.Returns((Vector3.left, Vector3.forward)),
new TestCaseData(Vector3.zero, Quaternion.identity, Vector3.one, true, true)
.SetName("At origin, use start and end transforms")
.Returns((Vector3.left, Vector3.right)),
new TestCaseData(Vector3.one, Quaternion.identity, Vector3.one, false, false)
.SetName("Offset from origin, use start and end points")
.Returns((Vector3.one + Vector3.back, Vector3.one + Vector3.forward)),
new TestCaseData(Vector3.one, Quaternion.identity, Vector3.one, false, true)
.SetName("Offset from origin, use start point and end transform")
.Returns((Vector3.one + Vector3.back, Vector3.right)),
new TestCaseData(Vector3.one, Quaternion.identity, Vector3.one, true, false)
.SetName("Offset from origin, use start transform and end point")
.Returns((Vector3.left, Vector3.one + Vector3.forward)),
new TestCaseData(Vector3.one, Quaternion.identity, Vector3.one, true, true)
.SetName("Offset from origin, use start and end transforms")
.Returns((Vector3.left, Vector3.right)),
new TestCaseData(Vector3.zero, k_RotatedAroundYAxis, Vector3.one, false, false)
.SetName("Rotated at origin, use start and end points")
.Returns((Vector3.forward, Vector3.back)),
new TestCaseData(Vector3.zero, k_RotatedAroundYAxis, Vector3.one, false, true)
.SetName("Rotated at origin, use start point and end transform")
.Returns((Vector3.forward, Vector3.right)),
new TestCaseData(Vector3.zero, k_RotatedAroundYAxis, Vector3.one, true, false)
.SetName("Rotated at origin, use start transform and end point")
.Returns((Vector3.left, Vector3.back)),
new TestCaseData(Vector3.zero, k_RotatedAroundYAxis, Vector3.one, true, true)
.SetName("Rotated at origin, use start and end transforms")
.Returns((Vector3.left, Vector3.right)),
new TestCaseData(Vector3.zero, Quaternion.identity, k_UniformScale, false, false)
.SetName("Scaled at origin, use start and end points")
.Returns((Vector3.back, Vector3.forward)),
new TestCaseData(Vector3.zero, Quaternion.identity, k_UniformScale, false, true)
.SetName("Scaled at origin, use start point and end transform")
.Returns((Vector3.back, Vector3.right)),
new TestCaseData(Vector3.zero, Quaternion.identity, k_UniformScale, true, false)
.SetName("Scaled at origin, use start transform and end point")
.Returns((Vector3.left, Vector3.forward)),
new TestCaseData(Vector3.zero, Quaternion.identity, k_UniformScale, true, true)
.SetName("Scaled at origin, use start and end transforms")
.Returns((Vector3.left, Vector3.right)),
};
[TestCaseSource(nameof(k_TestCases))]
public (Vector3 start, Vector3 end) GetWorldPositions_ReturnsExpectedResults(
Vector3 transformPosition, Quaternion transformRotation, Vector3 transformScale,
bool useStartTransform, bool useEndTransform
)
{
m_NavMeshLink.transform.position = transformPosition;
m_NavMeshLink.transform.rotation = transformRotation;
m_NavMeshLink.transform.localScale = transformScale;
m_NavMeshLink.startTransform = useStartTransform ? m_StartTransform : null;
m_NavMeshLink.endTransform = useEndTransform ? m_EndTransform : null;
m_NavMeshLink.GetWorldPositions(out var worldStart, out var worldEnd);
return (start: worldStart, end: worldEnd);
}
// The expected values have been obtained by observing a correct result in the Editor
static readonly TestCaseData[] k_SkewedTestCases =
{
new TestCaseData(Vector3.zero, Quaternion.identity, Vector3.one,
new Vector3(2f, 1f, 0f), new Vector3(2f, 1f, 2f))
.SetName("At parent origin"),
new TestCaseData(Vector3.zero, k_ArbitraryRotationAroundYAxis, Vector3.one,
new Vector3(1.577382f, 1f, 0.09369224f), new Vector3(2.422618f, 1f, 1.906308f))
.SetName("Rotated"),
new TestCaseData(Vector3.one, k_ArbitraryRotationAroundYAxis, Vector3.one,
new Vector3(3.577382f, 2f, 0.7936923f), new Vector3(4.422618f, 2f, 2.606308f))
.SetName("Offset from parent"),
new TestCaseData(Vector3.zero, Quaternion.identity, k_UniformScale,
new Vector3(2f, 1f, 0f), new Vector3(2f, 1f, 2f))
.SetName("Scaled"),
new TestCaseData(Vector3.one, k_ArbitraryRotationAroundYAxis, k_UniformScale,
new Vector3(3.577382f, 2f, 0.7936923f), new Vector3(4.422618f, 2f, 2.606308f))
.SetName("Rotated, scaled and with offset")
};
[TestCaseSource(nameof(k_SkewedTestCases))]
public void GetWorldPositionsForPoints_WhenLinkParentHasUnevenScale_ReturnsEndpointsNonSkewed(
Vector3 transformPosition, Quaternion transformRotation, Vector3 transformScale,
Vector3 expectedStart, Vector3 expectedEnd)
{
m_NavMeshLink.transform.parent = m_ScaledSkewer.transform;
m_NavMeshLink.transform.localPosition = transformPosition;
m_NavMeshLink.transform.localRotation = transformRotation;
m_NavMeshLink.transform.localScale = transformScale;
m_NavMeshLink.startTransform = null;
m_NavMeshLink.endTransform = null;
Assume.That(Vector3.zero, Is.Not.EqualTo(m_NavMeshLink.startPoint).Or.Not.EqualTo(m_NavMeshLink.endPoint),
"At least one endpoint should be skewed away from the local origin.");
m_LinkImitator.transform.parent = m_ScaledSkewer.transform;
m_LinkImitator.transform.localPosition = transformPosition;
m_LinkImitator.transform.localRotation = transformRotation;
m_LinkImitator.transform.localScale = transformScale;
m_LinkStartImitator.transform.localPosition = m_NavMeshLink.startPoint;
m_LinkEndImitator.transform.localPosition = m_NavMeshLink.endPoint;
Assume.That(m_LinkStartImitator.transform.position, Is.Not.EqualTo(expectedStart)
.Using(Vector3EqualityComparer.Instance),
"The wanted link start position should not be skewed along with the transform hierarchy.");
Assume.That(m_LinkEndImitator.transform.position, Is.Not.EqualTo(expectedEnd)
.Using(Vector3EqualityComparer.Instance),
"The wanted link end position should not be skewed along with the transform hierarchy.");
m_NavMeshLink.GetWorldPositions(out var worldStart, out var worldEnd);
// Uncomment to get the new expected values if you change the setup
//Debug.Log($"(new Vector3({worldStart.x}f, {worldStart.y}f, {worldStart.z}f), new Vector3({worldEnd.x}f, {worldEnd.y}f, {worldEnd.z}f))");
Assert.That(worldStart, Is.EqualTo(expectedStart)
.Using(Vector3EqualityComparer.Instance),
"Start position should be at an unscaled offset from the Link.");
Assert.That(worldEnd, Is.EqualTo(expectedEnd)
.Using(Vector3EqualityComparer.Instance),
"End position should be at an unscaled offset from the Link.");
}
static readonly Vector3 k_DoubleOne = 2f * Vector3.one;
static readonly TestCaseData[] k_TestCasesForLocal =
{
new TestCaseData(false, false, Vector3.one, -Vector3.one)
.SetName("From start and end points"),
new TestCaseData(false, true, Vector3.one, -k_DoubleOne)
.SetName("From start point and end transform"),
new TestCaseData(true, false, k_DoubleOne, -Vector3.one)
.SetName("From start transform and end point"),
new TestCaseData(true, true, k_DoubleOne, -k_DoubleOne)
.SetName("From start and end transforms")
};
[TestCaseSource(nameof(k_TestCasesForLocal))]
public void GetLocalPositions_ReturnsExpectedResults(
bool useStartTransform, bool useEndTransform,
Vector3 expectedStart, Vector3 expectedEnd)
{
var origin = Vector3.one;
m_NavMeshLink.transform.SetPositionAndRotation(origin, Quaternion.Euler(90f, -90f, 90f));
m_NavMeshLink.transform.localScale = k_DoubleOne;
m_StartTransform.position = origin - k_DoubleOne;
m_EndTransform.position = origin + k_DoubleOne;
m_NavMeshLink.enabled = false;
m_NavMeshLink.startTransform = useStartTransform ? m_StartTransform : null;
m_NavMeshLink.endTransform = useEndTransform ? m_EndTransform : null;
m_NavMeshLink.startPoint = !useStartTransform ? Vector3.one : 100f * Vector3.one;
m_NavMeshLink.endPoint = !useEndTransform ? -Vector3.one : -100f * Vector3.one;
m_NavMeshLink.enabled = true;
m_NavMeshLink.GetLocalPositions(out var localStart, out var localEnd);
Assert.That(localStart, Is.EqualTo(expectedStart).Using(Vector3EqualityComparer.Instance),
"Start should be reported at a different position.");
Assert.That(localEnd, Is.EqualTo(expectedEnd).Using(Vector3EqualityComparer.Instance),
"End should be reported at a different position.");
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2a2ea6cc04d4a4333b94b04c4d51c56c

View File

@@ -0,0 +1,106 @@
#if UNITY_EDITOR || UNITY_STANDALONE
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.TestTools;
namespace Unity.AI.Navigation.Tests
{
class NavMeshSurfaceAgentTests
{
NavMeshSurface m_Surface;
NavMeshAgent m_Agent;
[SetUp]
public void Setup()
{
m_Surface = GameObject.CreatePrimitive(PrimitiveType.Plane).AddComponent<NavMeshSurface>();
}
[TearDown]
public void TearDown()
{
Object.DestroyImmediate(m_Agent.gameObject);
Object.DestroyImmediate(m_Surface.gameObject);
m_Agent = null;
m_Surface = null;
}
[Test]
public void AgentIdentifiesSurfaceOwner()
{
m_Surface.BuildNavMesh();
m_Agent = new GameObject("Agent").AddComponent<NavMeshAgent>();
Assert.AreEqual(m_Surface, m_Agent.navMeshOwner);
Assert.IsTrue(m_Agent.isOnNavMesh);
}
[Test]
[Ignore("1012991 : Missing functionality for notifying the NavMeshAgent about the removal of the NavMesh.")]
public void AgentDetachesAndAttachesToSurface()
{
m_Surface.BuildNavMesh();
m_Agent = new GameObject("Agent").AddComponent<NavMeshAgent>();
Assert.AreEqual(m_Surface, m_Agent.navMeshOwner);
Assert.IsTrue(m_Agent.isOnNavMesh);
m_Surface.enabled = false;
Assert.IsNull(m_Agent.navMeshOwner);
Assert.IsFalse(m_Agent.isOnNavMesh);
m_Surface.enabled = true;
Assert.AreEqual(m_Surface, m_Agent.navMeshOwner);
Assert.IsTrue(m_Agent.isOnNavMesh);
}
/*
[Test]
public void AgentIsOnNavMeshWhenMatchingAgentTypeID()
{
m_Surface.agentTypeID = 1234;
m_Surface.BuildNavMesh();
m_Agent = new GameObject("Agent").AddComponent<NavMeshAgent>();
Assert.IsFalse(m_Agent.isOnNavMesh);
m_Agent.agentTypeID = 1234;
Assert.IsTrue(m_Agent.isOnNavMesh);
}
*/
[UnityTest]
public IEnumerator AgentAlignsToSurfaceNextFrame()
{
m_Surface.transform.rotation = new Quaternion(-0.679622f, 0.351242f, -0.373845f, 0.524388f);
m_Surface.BuildNavMesh();
m_Agent = new GameObject("Agent").AddComponent<NavMeshAgent>();
yield return null;
var residual = m_Surface.transform.up - m_Agent.transform.up;
Assert.IsTrue(residual.magnitude < 0.01f);
}
[UnityTest]
public IEnumerator AgentDoesNotAlignToSurfaceNextFrame()
{
m_Surface.transform.rotation = new Quaternion(-0.679622f, 0.351242f, -0.373845f, 0.524388f);
m_Surface.BuildNavMesh();
m_Agent = new GameObject("Agent").AddComponent<NavMeshAgent>();
m_Agent.updateUpAxis = false;
yield return null;
var residual = Vector3.up - m_Agent.transform.up;
Assert.IsTrue(residual.magnitude < 0.01f);
}
}
}
#endif

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 45e898f1334e740678c21331ac30d746
timeCreated: 1490606318
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,15 @@
using UnityEngine;
namespace Unity.AI.Navigation.Tests
{
[DefaultExecutionOrder(-1)]
class NavMeshSurfaceBuildFromAwake : MonoBehaviour
{
public NavMeshSurface surface;
void Awake()
{
surface.BuildNavMesh();
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e6be2106b2f72df4199763945ec1f6ec

View File

@@ -0,0 +1,966 @@
#if UNITY_EDITOR || UNITY_STANDALONE
using System;
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.TestTools;
using UnityEngine.TestTools.Utils;
using Object = UnityEngine.Object;
namespace Unity.AI.Navigation.Tests
{
[TestFixture]
class NavMeshSurfaceLinkTests
{
GameObject m_PlaneAtOrigin;
GameObject m_PlaneOnTheSide;
NavMeshLink m_Link;
NavMeshSurface m_Surface;
readonly Vector3 m_OffsetX = new(11f, 0f, 0f);
readonly Vector3 m_OffsetZ = new(0f, 0f, 11f);
readonly Vector3 m_DefaultEndpointOffset = new(0f, 0f, 2.5f);
readonly int m_PandaTypeID = NavMesh.CreateSettings().agentTypeID;
const int k_AreaTypeForPanda = 3;
NavMeshAgent m_Agent;
GameObject m_ExtraNavMesh;
GameObject m_FarFromNavMesh;
GameObject m_TempGO;
GameObject m_PathfindingStart;
GameObject m_PathfindingEnd;
NavMeshDataInstance m_NavMeshClone;
NavMeshDataInstance m_NavMeshForPanda;
NavMeshSurface m_SurfaceForPanda;
[OneTimeSetUp]
public void OneTimeSetUp()
{
m_PlaneAtOrigin = GameObject.CreatePrimitive(PrimitiveType.Plane);
m_PlaneOnTheSide = GameObject.CreatePrimitive(PrimitiveType.Plane);
m_PlaneOnTheSide.transform.position = m_OffsetX;
m_PlaneOnTheSide.transform.localScale = 0.4f * Vector3.one;
m_PlaneAtOrigin.transform.localScale = 0.4f * Vector3.one;
m_Surface = new GameObject("Surface").AddComponent<NavMeshSurface>();
m_Surface.BuildNavMesh();
Assume.That(HasPathConnecting(m_PlaneAtOrigin, m_PlaneOnTheSide), Is.False);
Assume.That(HasPathConnecting(m_PlaneOnTheSide, m_PlaneAtOrigin), Is.False);
m_Agent = new GameObject("Agent").AddComponent<NavMeshAgent>();
m_Agent.transform.position = m_PlaneOnTheSide.transform.position - 2f * Vector3.back;
m_Agent.enabled = false;
m_Agent.acceleration = 100f;
m_Agent.speed = 10f;
Assume.That(m_Agent.speed, Is.LessThan(m_OffsetX.x),
"Too high of a speed causes the agent to jump straight to the path's end.");
m_PathfindingStart = new GameObject("Path Start");
m_PathfindingEnd = new GameObject("Path End");
m_ExtraNavMesh = new GameObject("Origin of Additional NavMesh")
{
transform =
{
position = m_PlaneAtOrigin.transform.position + m_OffsetZ
}
};
m_FarFromNavMesh = new GameObject("Position Far From NavMesh")
{
transform =
{
position = m_ExtraNavMesh.transform.position - 2f * m_OffsetX
}
};
m_NavMeshClone = NavMesh.AddNavMeshData(m_Surface.navMeshData, m_ExtraNavMesh.transform.position, Quaternion.identity);
m_SurfaceForPanda = m_Surface.gameObject.AddComponent<NavMeshSurface>();
m_SurfaceForPanda.agentTypeID = m_PandaTypeID;
m_SurfaceForPanda.defaultArea = k_AreaTypeForPanda;
m_SurfaceForPanda.BuildNavMesh();
m_SurfaceForPanda.enabled = false;
}
[SetUp]
public void SetUp()
{
// move m_Link to OneTimeSetup
m_Link = new GameObject("Link").AddComponent<NavMeshLink>();
m_Link.transform.position = Vector3.zero;
m_Link.startPoint = m_PlaneAtOrigin.transform.position;
m_Link.endPoint = m_PlaneOnTheSide.transform.position;
m_Link.UpdateLink();
Assume.That(HasPathConnecting(m_PlaneAtOrigin, m_PlaneOnTheSide), Is.True);
Assume.That(HasPathConnecting(m_PlaneOnTheSide, m_PlaneAtOrigin), Is.True);
if (m_Agent.isActiveAndEnabled)
{
m_Agent.ResetPath();
m_Agent.Warp(m_PlaneOnTheSide.transform.position - 2f * Vector3.back);
}
m_PathfindingStart.transform.position = m_Link.transform.position + m_Link.startPoint;
m_PathfindingEnd.transform.position = m_Link.transform.position + m_Link.endPoint;
}
[TearDown]
public void TearDown()
{
Object.DestroyImmediate(m_Link.gameObject);
if (m_TempGO != null)
Object.DestroyImmediate(m_TempGO);
if (m_NavMeshForPanda.valid)
NavMesh.RemoveNavMeshData(m_NavMeshForPanda);
m_Agent.enabled = false;
}
[OneTimeTearDown]
public void OneTimeTearDown()
{
Object.DestroyImmediate(m_Surface.gameObject);
Object.DestroyImmediate(m_PlaneAtOrigin);
Object.DestroyImmediate(m_PlaneOnTheSide);
Object.DestroyImmediate(m_Agent);
Object.DestroyImmediate(m_ExtraNavMesh);
Object.DestroyImmediate(m_FarFromNavMesh);
Object.DestroyImmediate(m_PathfindingStart);
Object.DestroyImmediate(m_PathfindingEnd);
if (m_NavMeshClone.valid)
NavMesh.RemoveNavMeshData(m_NavMeshClone);
}
[Test]
public void Link_WhenCreated_HasDefaultEndpointOffsets()
{
var link = m_Link.gameObject.AddComponent<NavMeshLink>();
Assert.That(link.startPoint, Is.EqualTo(-m_DefaultEndpointOffset).Using(Vector3EqualityComparer.Instance),
"Newly created NavMeshLink should have the start point located at an offset from the game object.");
Assert.That(link.endPoint, Is.EqualTo(m_DefaultEndpointOffset).Using(Vector3EqualityComparer.Instance),
"Newly created NavMeshLink should have the end point located at an offset from the game object.");
}
[Test]
public void Link_WhenCreatedAtRuntime_HasNullStartAndEndTransforms()
{
var link = m_Link.gameObject.AddComponent<NavMeshLink>();
Assert.That(link.startTransform, Is.EqualTo(null),
"A NavMeshLink newly created should have a null start transform.");
Assert.That(link.endTransform, Is.EqualTo(null),
"A NavMeshLink newly created should have a null end transform.");
}
[Test]
public void Link_WhenCreated_HasTheExpectedValuesForProperties()
{
var link = m_Link.gameObject.AddComponent<NavMeshLink>();
Assert.That(link.area, Is.EqualTo(0),
"Newly created NavMeshLink should have the Walkable area type.");
Assert.That(link.agentTypeID, Is.EqualTo(0),
"Newly created NavMeshLink should have the Humanoid agent type ID.");
Assert.That(link.bidirectional, Is.True,
"Newly created NavMeshLink should have bidirectional switched on.");
Assert.That(link.costModifier, Is.Negative,
"Newly created NavMeshLink should have a negative cost modifier, which means the cost from area type is not overridden.");
Assert.That(link.width, Is.EqualTo(0f),
"Newly created NavMeshLink should have a width of zero.");
Assert.That(link.autoUpdate, Is.False,
"Newly created NavMeshLink should have autoUpdate switched off.");
Assert.That(link.activated, Is.True,
"Newly created NavMeshLink should be activated.");
}
[TestCase(0)]
[TestCase(1)]
[TestCase(-1)]
[TestCase(42)]
[TestCase(-42)]
public void CostModifier_SetValue_GetValueIsTheSame(int costModifier)
{
m_Link.costModifier = costModifier;
Assert.That(m_Link.costModifier, Is.EqualTo(costModifier));
}
[Test]
public void Link_WithValidParameters_ConnectsTwoSurfaces()
{
VerifyLinkConnection(ResultsIn.PathForward);
}
[Test]
public void Link_OnScaledObject_DoesNotScaleEndPoints()
{
m_Link.enabled = false;
m_Link.transform.localScale = new Vector3(1f, 1f, m_OffsetZ.z);
m_Link.startPoint = m_PlaneAtOrigin.transform.position + Vector3.forward;
m_Link.endPoint = m_PlaneOnTheSide.transform.position + Vector3.forward;
m_Link.enabled = true;
m_PathfindingStart.transform.position = m_Link.transform.TransformPoint(m_Link.startPoint);
m_PathfindingEnd.transform.position = m_Link.transform.TransformPoint(m_Link.endPoint);
VerifyLinkConnection(ResultsIn.NoPath);
m_PathfindingStart.transform.position = m_PlaneAtOrigin.transform.position;
m_PathfindingEnd.transform.position = m_PlaneOnTheSide.transform.position;
VerifyLinkConnection(ResultsIn.PathForward);
}
[Test]
public void Link_OnUpdateLinkWhileDisabled_DoesNotEnableConnection()
{
m_Link.gameObject.SetActive(false);
VerifyLinkConnection(ResultsIn.NoPath);
m_Link.UpdateLink();
VerifyLinkConnection(ResultsIn.NoPath);
}
[Test]
public void Link_OnUpdateLink_AppliesChangesImmediately()
{
m_Link.transform.rotation = Quaternion.Euler(0f, -90f, 0f);
m_Link.UpdateLink();
m_PathfindingEnd.transform.position = m_ExtraNavMesh.transform.position;
VerifyLinkConnection(ResultsIn.PathForward, m_Link.area, m_Link.agentTypeID);
}
[Test]
public void Link_WhenEnabled_AppliesChangesImmediately()
{
m_Link.enabled = false;
VerifyLinkConnection(ResultsIn.NoPath);
AddNavMeshForPandaAgent();
ReconfigureLinkForPandaAgent(m_Link);
m_PathfindingStart.transform.position = m_ExtraNavMesh.transform.position;
m_PathfindingEnd.transform.position = m_PlaneAtOrigin.transform.position;
VerifyLinkConnection(ResultsIn.NoPath, m_Link.area, m_Link.agentTypeID);
m_Link.enabled = true;
VerifyLinkConnection(ResultsIn.PathOnlyForward, m_Link.area, m_Link.agentTypeID);
}
void ReconfigureLinkForPandaAgent(NavMeshLink link)
{
var wasEnabled = link.enabled;
link.enabled = false;
link.agentTypeID = m_PandaTypeID;
link.area = k_AreaTypeForPanda;
link.bidirectional = false;
link.costModifier = 3f;
link.width = 6f;
link.startTransform = m_ExtraNavMesh.transform;
link.endTransform = m_PlaneAtOrigin.transform;
link.startPoint = 3f * Vector3.forward;
link.endPoint = 3f * Vector3.forward + Vector3.right;
link.enabled = wasEnabled;
}
void AddNavMeshForPandaAgent()
{
m_NavMeshForPanda = NavMesh.AddNavMeshData(m_SurfaceForPanda.navMeshData,
m_ExtraNavMesh.transform.position + 0.05f * Vector3.up, Quaternion.Euler(0f, 90f, 0f));
}
[Test]
public void Link_WhenGameObjectTransformMoves_EndpointsMoveRelativeToLinkOnUpdate()
{
m_Link.transform.position += Vector3.forward;
Assert.IsFalse(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, m_PlaneAtOrigin.transform.position + Vector3.forward));
Assert.IsFalse(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, m_PlaneOnTheSide.transform.position + Vector3.forward));
m_Link.UpdateLink();
Assert.IsTrue(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, m_PlaneAtOrigin.transform.position + Vector3.forward));
Assert.IsTrue(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, m_PlaneOnTheSide.transform.position + Vector3.forward));
}
[Test]
public void Link_WhenPropertyAreaChanges_UpdatesConnectionImmediately()
{
Assume.That(HasPathConnecting(m_PlaneAtOrigin, m_PlaneOnTheSide), Is.True);
m_Link.area = 4;
var anyAreaExceptTheLinkArea = ~(1 << m_Link.area);
Assert.IsFalse(HasPathConnecting(m_PlaneAtOrigin, m_PlaneOnTheSide, anyAreaExceptTheLinkArea));
}
[Test]
public void Link_WhenPropertyBidirectionalSwitchedOff_UpdatesConnectionImmediatelyToOneWay()
{
Assume.That(HasPathConnecting(m_PlaneOnTheSide, m_PlaneAtOrigin), Is.True);
m_Link.bidirectional = false;
VerifyLinkConnection(ResultsIn.PathOnlyForward);
}
[Test]
public void Link_WhenPropertyBidirectionalSwitchedOn_UpdatesConnectionImmediatelyToBothWays()
{
m_Link.bidirectional = false;
Assume.That(HasPathConnecting(m_PlaneOnTheSide, m_PlaneAtOrigin), Is.False);
m_Link.bidirectional = true;
VerifyLinkConnection(ResultsIn.PathBothWays);
}
[Test]
public void Link_WhenPropertyCostModifierChanges_UpdatesConnectionImmediately()
{
m_Link.gameObject.SetActive(false);
var fartherLink = m_Link.gameObject.AddComponent<NavMeshLink>();
fartherLink.startPoint = m_PlaneAtOrigin.transform.position + Vector3.forward;
fartherLink.endPoint = m_PlaneOnTheSide.transform.position + Vector3.forward;
m_Link.gameObject.SetActive(true);
Assume.That(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, m_Link.endPoint), Is.True);
m_Link.costModifier = 1000f;
Assert.IsFalse(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, m_Link.endPoint),
"A path should not go through the connection with the higher cost, even if it's closer.");
Assert.IsTrue(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, fartherLink.endPoint),
"A path should go through the connection with the lower cost, even if it's farther away.");
}
[Test]
public void Link_WhenPropertyStartPointChanged_UpdatesConnectionImmediately()
{
m_Link.startPoint = m_OffsetZ;
m_PathfindingStart.transform.position = m_ExtraNavMesh.transform.position;
VerifyLinkConnection(ResultsIn.PathForward);
}
[Test]
public void Link_WhenPropertyEndPointChanged_UpdatesConnectionImmediately()
{
m_Link.endPoint = m_OffsetZ;
m_PathfindingEnd.transform.position = m_ExtraNavMesh.transform.position;
VerifyLinkConnection(ResultsIn.PathForward);
}
[Test]
public void Link_WhenPropertyWidthChanges_UpdatesConnectionImmediately()
{
m_Link.transform.position = 3f * Vector3.forward;
m_Link.UpdateLink();
Assume.That(HasPathConnecting(m_PlaneAtOrigin, m_PlaneOnTheSide), Is.False);
m_Link.width = 6f;
Assert.IsTrue(HasPathConnecting(m_PlaneAtOrigin, m_PlaneOnTheSide));
}
[Test]
public void Link_WhenPropertyActivatedChanges_UpdatesConnectionImmediately()
{
m_Link.activated = false;
VerifyLinkConnection(ResultsIn.NoPath);
m_Link.activated = true;
VerifyLinkConnection(ResultsIn.PathForward);
}
[Test]
public void Link_WhenTransformAssignedAtStart_RetainsValueOfStartPoint()
{
m_TempGO = new GameObject("Link");
var link = m_TempGO.AddComponent<NavMeshLink>();
Assume.That(link.startPoint, Is.Not.EqualTo(Vector3.zero));
var startPointBefore = link.startPoint;
link.startTransform = m_ExtraNavMesh.transform;
link.UpdateLink();
Assert.That(link.startPoint, Is.EqualTo(startPointBefore),
"NavMeshLink should retain the start point after a start transform has been assigned to it.");
Assume.That(link.endPoint, Is.Not.EqualTo(Vector3.zero), "End point should retain a default offset.");
}
[Test]
public void Link_WhenTransformAssignedAtEnd_RetainsValueOfEndPoint()
{
m_TempGO = new GameObject("Link");
var link = m_TempGO.AddComponent<NavMeshLink>();
Assume.That(link.endPoint, Is.Not.EqualTo(Vector3.zero));
var endPointBefore = link.endPoint;
link.endTransform = m_ExtraNavMesh.transform;
link.UpdateLink();
Assert.That(link.endPoint, Is.EqualTo(endPointBefore),
"NavMeshLink should preserve the end point after an end transform has been assigned to it.");
Assume.That(link.startPoint, Is.Not.EqualTo(Vector3.zero), "Start point should keep a default offset.");
}
[Test]
public void Link_WhenTransformRemovedAtStart_KeepsStartPointUnchanged()
{
m_TempGO = new GameObject("Link");
var pointBefore = new Vector3(1f, 2f, 3f);
var link = m_TempGO.AddComponent<NavMeshLink>();
link.startTransform = m_TempGO.transform;
link.startPoint = pointBefore;
link.startTransform = null;
Assert.That(link.startPoint, Is.EqualTo(pointBefore),
"NavMeshLink should retain the same start point after the start transform has been unassigned.");
Assume.That(link.endPoint, Is.EqualTo(m_DefaultEndpointOffset),
"End point should keep a default offset.");
}
[Test]
public void Link_WhenTransformRemovedAtEnd_KeepsEndPointUnchanged()
{
m_TempGO = new GameObject("Link");
var pointBefore = new Vector3(1f, 2f, 3f);
var link = m_TempGO.AddComponent<NavMeshLink>();
link.endTransform = m_TempGO.transform;
link.endPoint = pointBefore;
link.endTransform = null;
Assert.That(link.endPoint, Is.EqualTo(pointBefore),
"NavMeshLink should retain the same end point after the end transform has been unassigned.");
Assume.That(link.startPoint, Is.EqualTo(-m_DefaultEndpointOffset),
"Start point should keep a default offset.");
}
[Test]
public void Link_WhenTransformAssignedAtStart_OverridesStartPointImmediately()
{
m_Link.startPoint = m_ExtraNavMesh.transform.position + m_OffsetX - m_Link.transform.position;
m_PathfindingStart.transform.position = m_ExtraNavMesh.transform.position + m_OffsetX;
VerifyLinkConnection(ResultsIn.PathForward);
m_Link.startTransform = m_ExtraNavMesh.transform;
VerifyLinkConnection(ResultsIn.NoPath);
m_PathfindingStart.transform.position = m_ExtraNavMesh.transform.position;
VerifyLinkConnection(ResultsIn.PathForward);
}
[Test]
public void Link_WhenTransformAssignedAtEnd_OverridesEndPointImmediately()
{
m_Link.endPoint = m_ExtraNavMesh.transform.position + m_OffsetX - m_Link.transform.position;
m_PathfindingEnd.transform.position = m_ExtraNavMesh.transform.position + m_OffsetX;
VerifyLinkConnection(ResultsIn.PathForward);
m_Link.endTransform = m_ExtraNavMesh.transform;
VerifyLinkConnection(ResultsIn.NoPath);
m_PathfindingEnd.transform.position = m_ExtraNavMesh.transform.position;
VerifyLinkConnection(ResultsIn.PathForward);
}
[Test]
public void Link_WhenTransformRemovedAtStart_FallsBackToStartPointImmediately()
{
m_TempGO = Object.Instantiate(m_ExtraNavMesh);
m_Link.enabled = false;
m_Link.startPoint = m_ExtraNavMesh.transform.position + m_OffsetX - m_Link.transform.position;
m_Link.startTransform = m_TempGO.transform;
m_Link.enabled = true;
m_PathfindingStart.transform.position = m_ExtraNavMesh.transform.position + m_OffsetX;
VerifyLinkConnection(ResultsIn.NoPath);
m_Link.startTransform = null;
VerifyLinkConnection(ResultsIn.PathForward);
}
[Test]
public void Link_WhenTransformRemovedAtEnd_FallsBackToEndPointImmediately()
{
m_TempGO = Object.Instantiate(m_ExtraNavMesh);
m_Link.enabled = false;
m_Link.endPoint = m_ExtraNavMesh.transform.position + m_OffsetX - m_Link.transform.position;
m_Link.endTransform = m_TempGO.transform;
m_Link.enabled = true;
m_PathfindingEnd.transform.position = m_ExtraNavMesh.transform.position + m_OffsetX;
VerifyLinkConnection(ResultsIn.NoPath);
m_Link.endTransform = null;
VerifyLinkConnection(ResultsIn.PathForward);
}
[Test]
public void Link_WhenBothTransformAndPointChangeAtStart_AppliesOnlyStartTransform()
{
m_Link.startTransform = m_ExtraNavMesh.transform;
m_Link.startPoint = -2f * m_OffsetX;
m_PathfindingStart.transform.position = m_ExtraNavMesh.transform.position;
VerifyLinkConnection(ResultsIn.PathForward);
}
[Test]
public void Link_WhenBothTransformAndPointChangeAtEnd_AppliesOnlyEndTransform()
{
m_Link.endTransform = m_ExtraNavMesh.transform;
m_Link.endPoint = -2f * m_OffsetX;
m_PathfindingEnd.transform.position = m_ExtraNavMesh.transform.position;
VerifyLinkConnection(ResultsIn.PathForward);
}
[UnityTest]
public IEnumerator Link_DuringAgentTraversal_ReportsIsOccupied_OtherwiseNotOccupied()
{
m_Agent.enabled = true;
m_Agent.SetDestination(m_PlaneAtOrigin.transform.position + Vector3.back);
while (!m_Agent.isOnOffMeshLink)
{
Assert.IsFalse(m_Link.occupied, "Link is occupied, but the agent hasn't arrived to the link yet.");
yield return null;
}
var framesUntilComplete = 3;
while (m_Agent.isOnOffMeshLink)
{
Assert.IsTrue(m_Link.occupied, "Link is not occupied, but the agent is on the link.");
if (--framesUntilComplete == 0)
m_Agent.CompleteOffMeshLink();
yield return null;
}
Assert.IsFalse(m_Link.occupied, "Link is occupied, but agent has left the link.");
}
[UnityTest]
public IEnumerator Link_WhenAutoUpdateSwitchedOn_UpdatesOnNextFrame_AndNotBefore()
{
Assume.That(m_Link.autoUpdate, Is.False);
m_Link.transform.rotation = Quaternion.Euler(0f, -90f, 0f);
m_PathfindingEnd.transform.position = m_ExtraNavMesh.transform.position;
m_Link.autoUpdate = true;
VerifyLinkConnection(ResultsIn.NoPath);
yield return null;
VerifyLinkConnection(ResultsIn.PathForward);
}
[UnityTest]
public IEnumerator Link_WhenAutoUpdateSwitchedOff_DoesNotApplyQueuedOrFutureChanges()
{
m_Link.autoUpdate = true;
yield return null;
m_Link.transform.rotation = Quaternion.Euler(0f, -90f, 0f);
Assume.That(m_PathfindingEnd.transform.position, Is.EqualTo(m_PlaneOnTheSide.transform.position).Using(Vector3EqualityComparer.Instance));
VerifyLinkConnection(ResultsIn.PathForward);
m_Link.autoUpdate = false;
yield return null;
VerifyLinkConnection(ResultsIn.PathForward);
m_Link.transform.SetPositionAndRotation(m_ExtraNavMesh.transform.position, Quaternion.identity);
yield return null;
VerifyLinkConnection(ResultsIn.PathForward);
}
[UnityTest]
public IEnumerator LinkWithAutoUpdateOn_WhenGameObjectMoves_UpdatesConnectionNextFrame()
{
m_Link.autoUpdate = true;
m_Link.transform.position += Vector3.forward;
Assert.IsFalse(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, m_PlaneAtOrigin.transform.position + Vector3.forward));
Assert.IsFalse(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, m_PlaneOnTheSide.transform.position + Vector3.forward));
yield return null;
Assert.IsTrue(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, m_PlaneAtOrigin.transform.position + Vector3.forward));
Assert.IsTrue(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, m_PlaneOnTheSide.transform.position + Vector3.forward));
}
[UnityTest]
public IEnumerator LinkWithAutoUpdateOff_WhenGameObjectMoves_KeepsConnectionUnchanged()
{
m_Link.autoUpdate = false;
Assume.That(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, m_PlaneAtOrigin.transform.position), Is.True);
Assert.That(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, m_PlaneOnTheSide.transform.position), Is.True);
m_Link.transform.position += Vector3.forward;
// Skip a few frames
yield return null;
yield return null;
yield return null;
Assert.IsTrue(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, m_PlaneAtOrigin.transform.position));
Assert.IsTrue(HasPathConnectingViaPoint(m_PlaneAtOrigin, m_PlaneOnTheSide, m_PlaneOnTheSide.transform.position));
}
[UnityTest]
public IEnumerator LinkWithAutoUpdateOn_WhenGameObjectRotates_UpdatesConnectionNextFrame()
{
m_Link.autoUpdate = true;
m_Link.transform.rotation = Quaternion.Euler(0f, -90f, 0f);
m_PathfindingEnd.transform.position = m_ExtraNavMesh.transform.position;
VerifyLinkConnection(ResultsIn.NoPath);
yield return null;
VerifyLinkConnection(ResultsIn.PathForward);
}
[UnityTest]
public IEnumerator LinkWithAutoUpdateOff_WhenGameObjectRotates_KeepsConnectionUnchanged()
{
m_Link.autoUpdate = false;
m_Link.transform.rotation = Quaternion.Euler(0f, -90f, 0f);
// Skip a few frames
yield return null;
yield return null;
yield return null;
Assume.That(m_PathfindingEnd.transform.position, Is.EqualTo(m_PlaneOnTheSide.transform.position).Using(Vector3EqualityComparer.Instance));
VerifyLinkConnection(ResultsIn.PathForward);
}
[UnityTest]
public IEnumerator LinkWithAutoUpdateOn_WhenTransformAtStartMoves_UpdatesConnectionNextFrame()
{
m_TempGO = Object.Instantiate(m_FarFromNavMesh);
m_Link.startTransform = m_TempGO.transform;
m_Link.UpdateLink();
m_Link.autoUpdate = true;
m_TempGO.transform.position += 2f * m_OffsetX;
m_PathfindingStart.transform.position = m_TempGO.transform.position;
VerifyLinkConnection(ResultsIn.NoPath);
yield return null;
VerifyLinkConnection(ResultsIn.PathForward);
}
[UnityTest]
public IEnumerator LinkWithAutoUpdateOn_WhenTransformAtEndMoves_UpdatesConnectionNextFrame()
{
m_TempGO = Object.Instantiate(m_FarFromNavMesh);
m_Link.endTransform = m_TempGO.transform;
m_Link.UpdateLink();
m_Link.autoUpdate = true;
m_TempGO.transform.position += 2f * m_OffsetX;
m_PathfindingEnd.transform.position = m_TempGO.transform.position;
VerifyLinkConnection(ResultsIn.NoPath);
yield return null;
VerifyLinkConnection(ResultsIn.PathForward);
}
[UnityTest]
public IEnumerator LinkWithAutoUpdateOn_WhenTransformAtStartDestroyed_AppliesStartPointNextFrame()
{
m_Link.autoUpdate = true;
m_TempGO = Object.Instantiate(m_ExtraNavMesh);
m_Link.enabled = false;
m_Link.startTransform = m_TempGO.transform;
m_Link.startPoint = m_PlaneOnTheSide.transform.position - m_Link.transform.position;
m_Link.endTransform = null;
m_Link.endPoint = Vector3.zero;
m_Link.bidirectional = false;
m_Link.enabled = true;
m_PathfindingStart.transform.position = m_TempGO.transform.position;
m_PathfindingEnd.transform.position = m_PlaneAtOrigin.transform.position;
Object.DestroyImmediate(m_TempGO);
VerifyLinkConnection(ResultsIn.PathForward);
yield return null;
VerifyLinkConnection(ResultsIn.NoPath);
m_PathfindingStart.transform.position = m_PlaneOnTheSide.transform.position;
VerifyLinkConnection(ResultsIn.PathForward);
}
[UnityTest]
public IEnumerator LinkWithAutoUpdateOn_WhenTransformAtEndDestroyed_AppliesEndPointNextFrame()
{
m_Link.autoUpdate = true;
m_TempGO = Object.Instantiate(m_ExtraNavMesh);
m_Link.enabled = false;
m_Link.startTransform = null;
m_Link.startPoint = m_PlaneOnTheSide.transform.position - m_Link.transform.position;
m_Link.endTransform = m_TempGO.transform;
m_Link.endPoint = Vector3.zero;
m_Link.bidirectional = false;
m_Link.enabled = true;
m_PathfindingStart.transform.position = m_PlaneOnTheSide.transform.position;
m_PathfindingEnd.transform.position = m_TempGO.transform.position;
Object.DestroyImmediate(m_TempGO);
VerifyLinkConnection(ResultsIn.PathForward);
yield return null;
VerifyLinkConnection(ResultsIn.NoPath);
m_PathfindingEnd.transform.position = m_PlaneAtOrigin.transform.position;
VerifyLinkConnection(ResultsIn.PathForward);
}
[UnityTest]
public IEnumerator LinkWithAutoUpdateOff_WhenTransformAtStartMoves_KeepsConnectionUnchanged()
{
m_Link.autoUpdate = false;
m_TempGO = Object.Instantiate(m_ExtraNavMesh);
m_Link.startTransform = m_TempGO.transform;
m_Link.UpdateLink();
m_PathfindingStart.transform.position = m_TempGO.transform.position;
VerifyLinkConnection(ResultsIn.PathForward);
m_TempGO.transform.position += m_OffsetX;
yield return null;
yield return null;
yield return null;
VerifyLinkConnection(ResultsIn.PathForward);
m_PathfindingStart.transform.position = m_TempGO.transform.position;
VerifyLinkConnection(ResultsIn.NoPath);
}
[UnityTest]
public IEnumerator LinkWithAutoUpdateOff_WhenTransformAtEndMoves_KeepsConnectionUnchanged()
{
m_Link.autoUpdate = false;
m_TempGO = Object.Instantiate(m_ExtraNavMesh);
m_Link.endTransform = m_TempGO.transform;
m_Link.UpdateLink();
m_PathfindingEnd.transform.position = m_TempGO.transform.position;
VerifyLinkConnection(ResultsIn.PathForward);
m_TempGO.transform.position += m_OffsetX;
yield return null;
yield return null;
yield return null;
VerifyLinkConnection(ResultsIn.PathForward);
m_PathfindingEnd.transform.position = m_TempGO.transform.position;
VerifyLinkConnection(ResultsIn.NoPath);
}
#pragma warning disable CS0618 // Test deprecated members
[Test]
public void Link_WhenCreated_HasTheExpectedValuesForDeprecatedProperties()
{
var link = m_Link.gameObject.AddComponent<NavMeshLink>();
Assert.That(link.biDirectional, Is.True,
"Newly created NavMeshLink should have deprecated biDirectional switched on.");
Assert.That(link.autoUpdatePositions, Is.False,
"Newly created NavMeshLink should have deprecated autoUpdatePositions switched off.");
Assert.That(link.costOverride, Is.Negative,
"Newly created NavMeshLink should have a negative deprecated cost override, which means the cost from area type is not overridden.");
}
[Test]
public void Link_WhenBidirectionalChanges_DeprecatedBiDirectionalChangesToo()
{
m_Link.bidirectional = false;
Assert.That(m_Link.biDirectional, Is.False);
m_Link.bidirectional = true;
Assert.That(m_Link.biDirectional, Is.True);
}
[Test]
public void Link_WhenDeprecatedBiDirectionalChanges_BidirectionalChangesToo()
{
m_Link.biDirectional = false;
Assert.That(m_Link.bidirectional, Is.False);
m_Link.biDirectional = true;
Assert.That(m_Link.bidirectional, Is.True);
}
[Test]
public void Link_WhenAutoUpdateChanges_DeprecatedAutoUpdatePositionsChangesToo()
{
m_Link.autoUpdate = true;
Assert.That(m_Link.autoUpdatePositions, Is.True);
m_Link.autoUpdate = false;
Assert.That(m_Link.autoUpdatePositions, Is.False);
}
[Test]
public void Link_WhenDeprecatedAutoUpdatePositionsChanges_AutoUpdateChangesToo()
{
m_Link.autoUpdatePositions = true;
Assert.That(m_Link.autoUpdate, Is.True);
m_Link.autoUpdatePositions = false;
Assert.That(m_Link.autoUpdate, Is.False);
}
[Test]
public void Link_WhenCostModifierChanges_DeprecatedCostOverrideChangesToo()
{
m_Link.costModifier = 1f;
Assert.That(m_Link.costOverride, Is.EqualTo(1f));
m_Link.costModifier = 0f;
Assert.That(m_Link.costOverride, Is.EqualTo(0f));
m_Link.costModifier = -4.123f;
Assert.That(m_Link.costOverride, Is.EqualTo(-4.123f));
}
[Test]
public void Link_WhenDeprecatedCostOverrideChanges_CostModifierChangesToo()
{
m_Link.costOverride = 1f;
Assert.That(m_Link.costModifier, Is.EqualTo(1f));
m_Link.costOverride = 0f;
Assert.That(m_Link.costModifier, Is.EqualTo(0f));
m_Link.costOverride = -4.123f;
Assert.That(m_Link.costModifier, Is.EqualTo(-4.123f));
}
[Test]
public void Link_OnDeprecatedUpdatePositions_AppliesChangesImmediately()
{
m_Link.transform.rotation = Quaternion.Euler(0f, -90f, 0f);
m_Link.UpdatePositions();
m_PathfindingEnd.transform.position = m_ExtraNavMesh.transform.position;
VerifyLinkConnection(ResultsIn.PathForward, m_Link.area, m_Link.agentTypeID);
}
#pragma warning restore CS0618
internal enum ResultsIn
{
PathForward,
PathOnlyForward,
PathBothWays,
NoPath
}
void VerifyLinkConnection(ResultsIn expected,
int areaType = 0,
int agentTypeID = 0)
{
var forwardWanted = expected != ResultsIn.NoPath;
try
{
Assert.That(HasPathConnecting(m_PathfindingStart, m_PathfindingEnd, 1 << areaType, agentTypeID), Is.EqualTo(forwardWanted),
forwardWanted ? "The NavMesh patches should be connected." : "The NavMesh patches should not be connected.");
}
catch (AssertionException)
{
Debug.Log($"The NavMesh patches at {m_PathfindingStart.transform.position} and {m_PathfindingEnd.transform.position} should {(forwardWanted ? "" : "not ")}be connected (agent={NavMesh.GetSettingsNameFromID(agentTypeID)}, area={areaType}).");
throw;
}
if (expected != ResultsIn.PathForward && expected != ResultsIn.NoPath)
{
var backwardWanted = expected == ResultsIn.PathBothWays;
try
{
Assert.That(HasPathConnecting(m_PathfindingEnd, m_PathfindingStart, 1 << areaType, agentTypeID), Is.EqualTo(backwardWanted),
backwardWanted ? "The NavMesh patches should be connected backward." : "The NavMesh patches should not be connected backward.");
}
catch (AssertionException)
{
Debug.Log($"The NavMesh patches at {m_PathfindingStart.transform.position} and {m_PathfindingEnd.transform.position} should {(backwardWanted ? "" : "not ")}be connected backward (agent={NavMesh.GetSettingsNameFromID(agentTypeID)}, area={areaType}).");
throw;
}
}
}
static bool HasPathConnecting(GameObject a, GameObject b, int areaMask = NavMesh.AllAreas, int agentTypeID = 0)
{
var path = new NavMeshPath();
var filter = new NavMeshQueryFilter
{
areaMask = areaMask,
agentTypeID = agentTypeID
};
NavMesh.CalculatePath(a.transform.position, b.transform.position, filter, path);
return path.status == NavMeshPathStatus.PathComplete;
}
static bool HasPathConnectingViaPoint(GameObject a, GameObject b, Vector3 point, int areaMask = NavMesh.AllAreas, int agentTypeID = 0)
{
var path = new NavMeshPath();
var filter = new NavMeshQueryFilter
{
areaMask = areaMask,
agentTypeID = agentTypeID
};
NavMesh.CalculatePath(a.transform.position, b.transform.position, filter, path);
if (path.status != NavMeshPathStatus.PathComplete)
return false;
var pathCorners = path.corners;
for (var i = 1; i < pathCorners.Length - 1; i++)
{
var corner = pathCorners[i];
if (Vector3.Distance(corner, point) < 0.1f)
return true;
}
return false;
}
}
}
#endif

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 264ca61ae1b6e4c16bcfc55f84300402
timeCreated: 1490606318
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,133 @@
#if UNITY_EDITOR || UNITY_STANDALONE
using NUnit.Framework;
using UnityEngine;
using UnityEngine.AI;
namespace Unity.AI.Navigation.Tests
{
[TestFixture]
class NavMeshSurfaceModifierTests
{
NavMeshSurface m_Surface;
NavMeshModifier m_Modifier;
NavMeshSurfaceBuildFromAwake m_BuildOnAwake;
[SetUp]
public void CreatePlaneWithModifier()
{
var plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
m_Surface = plane.AddComponent<NavMeshSurface>();
m_Modifier = plane.AddComponent<NavMeshModifier>();
}
[TearDown]
public void DestroyPlaneWithModifier()
{
Object.DestroyImmediate(m_Modifier.gameObject);
}
[Test]
public void ModifierIgnoreAffectsSelf()
{
m_Modifier.ignoreFromBuild = true;
m_Surface.BuildNavMesh();
Assert.IsFalse(NavMeshSurfaceTests.HasNavMeshAtOrigin());
}
[Test]
public void ModifierIgnoreAffectsChild()
{
m_Modifier.ignoreFromBuild = true;
m_Modifier.GetComponent<MeshRenderer>().enabled = false;
var childPlane = GameObject.CreatePrimitive(PrimitiveType.Plane);
childPlane.transform.SetParent(m_Modifier.transform);
m_Surface.BuildNavMesh();
Assert.IsFalse(NavMeshSurfaceTests.HasNavMeshAtOrigin());
Object.DestroyImmediate(childPlane);
}
[Test]
public void ModifierIgnoreDoesNotAffectSibling()
{
m_Modifier.ignoreFromBuild = true;
m_Modifier.GetComponent<MeshRenderer>().enabled = false;
var siblingPlane = GameObject.CreatePrimitive(PrimitiveType.Plane);
m_Surface.BuildNavMesh();
Assert.IsTrue(NavMeshSurfaceTests.HasNavMeshAtOrigin());
Object.DestroyImmediate(siblingPlane);
}
[Test]
public void ModifierOverrideAreaAffectsSelf()
{
m_Modifier.area = 4;
m_Modifier.overrideArea = true;
m_Surface.BuildNavMesh();
var expectedAreaMask = 1 << 4;
Assert.IsTrue(NavMeshSurfaceTests.HasNavMeshAtOrigin(expectedAreaMask));
}
[Test]
public void Modifier_WhenSurfaceBuiltOnAwake_OverridesArea()
{
m_Modifier.gameObject.SetActive(false);
m_BuildOnAwake = m_Modifier.gameObject.AddComponent<NavMeshSurfaceBuildFromAwake>();
m_BuildOnAwake.surface = m_Surface;
m_Modifier.area = 4;
m_Modifier.overrideArea = true;
// Enable the components to build the NavMesh on Awake
m_Modifier.gameObject.SetActive(true);
NavMesh.SamplePosition(Vector3.zero, out var hit, 0.1f, NavMesh.AllAreas);
Assume.That(hit.hit, Is.True, "There should be a NavMesh at position (0,0,0).");
Assert.That(hit.mask, Is.EqualTo(1 << m_Modifier.area),
"The NavMesh should have the Modifier area mask at position (0,0,0).");
}
[Test]
public void ModifierOverrideAreaAffectsChild()
{
m_Modifier.area = 4;
m_Modifier.overrideArea = true;
m_Modifier.GetComponent<MeshRenderer>().enabled = false;
var childPlane = GameObject.CreatePrimitive(PrimitiveType.Plane);
childPlane.transform.SetParent(m_Modifier.transform);
m_Surface.BuildNavMesh();
var expectedAreaMask = 1 << 4;
Assert.IsTrue(NavMeshSurfaceTests.HasNavMeshAtOrigin(expectedAreaMask));
Object.DestroyImmediate(childPlane);
}
[Test]
public void ModifierOverrideAreaDoesNotAffectSibling()
{
m_Modifier.area = 4;
m_Modifier.overrideArea = true;
m_Modifier.GetComponent<MeshRenderer>().enabled = false;
var siblingPlane = GameObject.CreatePrimitive(PrimitiveType.Plane);
m_Surface.BuildNavMesh();
var expectedAreaMask = 1;
Assert.IsTrue(NavMeshSurfaceTests.HasNavMeshAtOrigin(expectedAreaMask));
Object.DestroyImmediate(siblingPlane);
}
}
}
#endif

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f9fe5cff05af44c0fb71a8dcc44efc41
timeCreated: 1490606318
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,71 @@
#if UNITY_EDITOR || UNITY_STANDALONE
using NUnit.Framework;
using UnityEngine;
namespace Unity.AI.Navigation.Tests
{
[TestFixture]
class NavMeshSurfaceModifierVolumeTests
{
NavMeshSurface surface;
NavMeshModifierVolume modifier;
[SetUp]
public void CreatePlaneAndModifierVolume()
{
var go = GameObject.CreatePrimitive(PrimitiveType.Plane);
surface = go.AddComponent<NavMeshSurface>();
modifier = new GameObject().AddComponent<NavMeshModifierVolume>();
}
[TearDown]
public void DestroyPlaneAndModifierVolume()
{
GameObject.DestroyImmediate(surface.gameObject);
GameObject.DestroyImmediate(modifier.gameObject);
}
[Test]
public void AreaAffectsNavMeshOverlapping()
{
modifier.center = Vector3.zero;
modifier.size = Vector3.one;
modifier.area = 4;
surface.BuildNavMesh();
var expectedAreaMask = 1 << 4;
Assert.IsTrue(NavMeshSurfaceTests.HasNavMeshAtOrigin(expectedAreaMask));
}
[Test]
public void AreaDoesNotAffectsNavMeshWhenNotOverlapping()
{
modifier.center = 1.1f * Vector3.right;
modifier.size = Vector3.one;
modifier.area = 4;
surface.BuildNavMesh();
var expectedAreaMask = 1;
Assert.IsTrue(NavMeshSurfaceTests.HasNavMeshAtOrigin(expectedAreaMask));
}
[Test]
public void BuildUsesOnlyIncludedModifierVolume()
{
modifier.center = Vector3.zero;
modifier.size = Vector3.one;
modifier.area = 4;
modifier.gameObject.layer = 7;
surface.layerMask = ~(1 << 7);
surface.BuildNavMesh();
var expectedAreaMask = 1;
Assert.IsTrue(NavMeshSurfaceTests.HasNavMeshAtOrigin(expectedAreaMask));
}
}
}
#endif

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f5d873c779b014234ba92f3cb7476da6
timeCreated: 1490606318
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,267 @@
#if UNITY_EDITOR || UNITY_STANDALONE
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.TestTools;
namespace Unity.AI.Navigation.Tests
{
[TestFixture]
class NavMeshSurfaceTests
{
GameObject plane;
NavMeshSurface surface;
[SetUp]
public void CreatePlaneWithSurface()
{
plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
surface = new GameObject().AddComponent<NavMeshSurface>();
Assert.IsFalse(HasNavMeshAtOrigin());
}
[TearDown]
public void DestroyPlaneWithSurface()
{
GameObject.DestroyImmediate(plane);
GameObject.DestroyImmediate(surface.gameObject);
Assert.IsFalse(HasNavMeshAtOrigin());
}
[Test]
public void NavMeshIsAvailableAfterBuild()
{
surface.BuildNavMesh();
Assert.IsTrue(HasNavMeshAtOrigin());
}
[Test]
public void NavMeshCanBeRemovedAndAdded()
{
surface.BuildNavMesh();
Assert.IsTrue(HasNavMeshAtOrigin());
surface.RemoveData();
Assert.IsFalse(HasNavMeshAtOrigin());
surface.AddData();
Assert.IsTrue(HasNavMeshAtOrigin());
}
[Test]
public void NavMeshIsNotAvailableWhenDisabled()
{
surface.BuildNavMesh();
surface.enabled = false;
Assert.IsFalse(HasNavMeshAtOrigin());
surface.enabled = true;
Assert.IsTrue(HasNavMeshAtOrigin());
}
[Test]
public void CanBuildWithCustomArea()
{
surface.defaultArea = 4;
var expectedAreaMask = 1 << 4;
surface.BuildNavMesh();
Assert.IsTrue(HasNavMeshAtOrigin(expectedAreaMask));
}
[Test]
public void CanBuildWithCustomAgentTypeID()
{
surface.agentTypeID = 1234;
surface.BuildNavMesh();
Assert.IsTrue(HasNavMeshAtOrigin(NavMesh.AllAreas, 1234));
}
[Test]
public void CanBuildCollidersAndIgnoreRenderMeshes()
{
plane.GetComponent<MeshRenderer>().enabled = false;
surface.useGeometry = NavMeshCollectGeometry.PhysicsColliders;
surface.BuildNavMesh();
Assert.IsTrue(HasNavMeshAtOrigin());
surface.useGeometry = NavMeshCollectGeometry.RenderMeshes;
surface.BuildNavMesh();
Assert.IsFalse(HasNavMeshAtOrigin());
}
[Test]
#if !NMC_CAN_ACCESS_PHYSICS
[Ignore("This test requires the com.unity.modules.physics package in order to run. Make sure to reference it in the project.")]
#endif
public void CanBuildRenderMeshesAndIgnoreColliders()
{
#if NMC_CAN_ACCESS_PHYSICS
plane.GetComponent<Collider>().enabled = false;
surface.useGeometry = NavMeshCollectGeometry.PhysicsColliders;
surface.BuildNavMesh();
Assert.IsFalse(HasNavMeshAtOrigin());
surface.useGeometry = NavMeshCollectGeometry.RenderMeshes;
surface.BuildNavMesh();
Assert.IsTrue(HasNavMeshAtOrigin());
#endif
}
[Test]
public void BuildIgnoresGeometryOutsideBounds()
{
surface.collectObjects = CollectObjects.Volume;
surface.center = new Vector3(20, 0, 0);
surface.size = new Vector3(10, 10, 10);
surface.BuildNavMesh();
Assert.IsFalse(HasNavMeshAtOrigin());
}
[Test]
public void BuildIgnoresGeometrySiblings()
{
surface.collectObjects = CollectObjects.Children;
surface.BuildNavMesh();
Assert.IsFalse(HasNavMeshAtOrigin());
}
[Test]
public void BuildDoesntCullAreaBiggerThanMinRegionArea()
{
// Move plane away from NavMesh tile's boundaries
plane.transform.localScale = new Vector3(0.25f, 0, 0.25f);
plane.transform.position = new Vector3(2.5f, 0, 7.5f);
surface.minRegionArea = 1f;
surface.BuildNavMesh();
Assert.IsTrue(HasNavMeshAtPosition(plane.transform.position));
}
[Test]
public void BuildCullsAreaSmallerThanMinRegionArea()
{
// Move plane away from NavMesh tile's boundaries
plane.transform.localScale = new Vector3(0.25f, 0, 0.25f);
plane.transform.position = new Vector3(2.5f, 0, 7.5f);
surface.minRegionArea = 5;
surface.BuildNavMesh();
Assert.IsFalse(HasNavMeshAtPosition(plane.transform.position));
}
[Test]
public void BuildUsesOnlyIncludedLayers()
{
plane.layer = 4;
surface.layerMask = ~(1 << 4);
surface.BuildNavMesh();
Assert.IsFalse(HasNavMeshAtOrigin());
}
[Test]
public void DefaultSettingsMatchBuiltinSettings()
{
var bs = surface.GetBuildSettings();
Assert.AreEqual(NavMesh.GetSettingsByIndex(0), bs);
}
[Test]
public void ActiveSurfacesContainsOnlyActiveAndEnabledSurface()
{
Assert.IsTrue(NavMeshSurface.activeSurfaces.Contains(surface));
Assert.AreEqual(1, NavMeshSurface.activeSurfaces.Count);
surface.enabled = false;
Assert.IsFalse(NavMeshSurface.activeSurfaces.Contains(surface));
Assert.AreEqual(0, NavMeshSurface.activeSurfaces.Count);
surface.enabled = true;
surface.gameObject.SetActive(false);
Assert.IsFalse(NavMeshSurface.activeSurfaces.Contains(surface));
Assert.AreEqual(0, NavMeshSurface.activeSurfaces.Count);
}
[UnityTest]
public IEnumerator NavMeshMovesToSurfacePositionNextFrame()
{
plane.transform.position = new Vector3(100, 0, 0);
surface.transform.position = new Vector3(100, 0, 0);
surface.BuildNavMesh();
Assert.IsFalse(HasNavMeshAtOrigin());
surface.transform.position = Vector3.zero;
Assert.IsFalse(HasNavMeshAtOrigin());
yield return null;
Assert.IsTrue(HasNavMeshAtOrigin());
}
[UnityTest]
public IEnumerator UpdatingAndAddingNavMesh()
{
var navMeshData = new NavMeshData();
var oper = surface.UpdateNavMesh(navMeshData);
Assert.IsFalse(HasNavMeshAtOrigin());
do
{
yield return null;
} while (!oper.isDone);
surface.RemoveData();
surface.navMeshData = navMeshData;
surface.AddData();
Assert.IsTrue(HasNavMeshAtOrigin());
}
[Test]
public void BuildTakesIntoAccountAdjacentWalkableSurfacesOutsideBounds()
{
surface.collectObjects = CollectObjects.Volume;
surface.center = new Vector3(0, 0, 0);
surface.size = new Vector3(10, 10, 10);
var adjacentPlane = GameObject.CreatePrimitive(PrimitiveType.Plane);
adjacentPlane.transform.position = new Vector3(10f, 0, 0);
surface.BuildNavMesh();
try
{
Assert.IsTrue(HasNavMeshAtPosition(new Vector3(surface.size.x / 2f, 0, 0)),
"A NavMesh should exists at the desired position.");
}
finally
{
Object.DestroyImmediate(adjacentPlane);
}
}
static bool HasNavMeshAtPosition(Vector3 position, int areaMask = NavMesh.AllAreas, int agentTypeID = 0)
{
var filter = new NavMeshQueryFilter {areaMask = areaMask, agentTypeID = agentTypeID};
return NavMesh.SamplePosition(position, out _, 0.1f, filter);
}
public static bool HasNavMeshAtOrigin(int areaMask = NavMesh.AllAreas, int agentTypeID = 0)
{
return HasNavMeshAtPosition(Vector3.zero, areaMask, agentTypeID);
}
}
}
#endif

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 925111c157b314873b97f89e0f03d570
timeCreated: 1490606318
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9c10f4966eb108848acf7461aaf6057e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
#if UNITY_EDITOR || UNITY_STANDALONE
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
namespace Unity.AI.Navigation.Tests
{
[TestFixture]
[PrebuildSetup("Unity.AI.Navigation.Tests." + nameof(SimpleScene2PlanesNavigationSetup))]
[PostBuildCleanup("Unity.AI.Navigation.Tests." + nameof(SimpleScene2PlanesNavigationSetup))]
class AddDynamicOffMeshLinkWorks : OffMeshLinkTestBase
{
const string k_SceneName = "OffMeshLinkTwoPlanesScene";
[UnitySetUp]
public IEnumerator UnitySetUp()
{
yield return SceneManager.LoadSceneAsync(k_SceneName, LoadSceneMode.Additive);
yield return null;
SceneManager.SetActiveScene(SceneManager.GetSceneByName(k_SceneName));
}
[UnityTest]
[UnityPlatform(exclude = new[] { RuntimePlatform.OSXServer, RuntimePlatform.WindowsServer, RuntimePlatform.LinuxServer })] //MTT-4133 Fails on Dedicated Server
public IEnumerator OffMeshLink_WhenAddedToGameObject_BecomesUsableImmediately()
{
CreateBiDirectionalLink(true);
m_Agent.SetDestination(m_PlaneEnd.position);
yield return null;
Assert.That(m_Agent.pathStatus, Is.EqualTo(NavMeshPathStatus.PathComplete), "DynamicOffMeshLink has not been created.");
}
[UnityTearDown]
public IEnumerator UnityTearDown()
{
yield return SceneManager.UnloadSceneAsync(k_SceneName);
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,61 @@
#if UNITY_EDITOR || UNITY_STANDALONE
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
using UnityEngine.TestTools.Utils;
namespace Unity.AI.Navigation.Tests
{
[TestFixture]
[Category("RegressionTest")]
[PrebuildSetup("Unity.AI.Navigation.Tests." + nameof(SimpleScene2PlanesNavigationSetup))]
[PostBuildCleanup("Unity.AI.Navigation.Tests." + nameof(SimpleScene2PlanesNavigationSetup))]
class AgentCustomLinkMovement : OffMeshLinkTestBase
{
const string k_SceneName = "OffMeshLinkTwoPlanesScene";
[UnitySetUp]
public IEnumerator UnitySetUp()
{
yield return SceneManager.LoadSceneAsync(k_SceneName, LoadSceneMode.Additive);
yield return null;
SceneManager.SetActiveScene(SceneManager.GetSceneByName(k_SceneName));
}
[UnityTest]
[UnityPlatform(exclude = new[] { RuntimePlatform.OSXServer, RuntimePlatform.WindowsServer, RuntimePlatform.LinuxServer })] //MTT-4133 Fails on Dedicated Server
public IEnumerator Agent_WithoutAutoTraverseOnOffMeshLink_DoesNotMoveByItself()
{
var link = CreateBiDirectionalLink(true);
m_Agent.autoTraverseOffMeshLink = false;
m_Agent.baseOffset = 1.0f;
m_Agent.transform.position = link.startTransform.position;
var hasDestination = m_Agent.SetDestination(link.endTransform.position);
Assert.That(hasDestination, Is.True, "NavMeshAgent destination has not been set.");
yield return null;
Assert.That(m_Agent.isOnOffMeshLink, Is.True, "NavMeshAgent is currently not positioned on NavMeshLink.");
// Move to gap between the NavMeshes connected by the NavMeshLink
var midAirPosition = new Vector3(17.71f, 3.92f, -6.66f);
m_Agent.transform.position = midAirPosition;
yield return null;
// Ensure the agent stays at this position - as 'autoTraverseOffMeshLink' is false
Assert.That(m_Agent.transform.position, Is.EqualTo(midAirPosition).Using(new Vector3EqualityComparer(0.01f)), "NavMeshAgent should be at midAirPosition.");
}
[UnityTearDown]
public IEnumerator UnityTearDown()
{
yield return SceneManager.UnloadSceneAsync(k_SceneName);
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,66 @@
#if UNITY_EDITOR || UNITY_STANDALONE
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
namespace Unity.AI.Navigation.Tests
{
[TestFixture]
[Category("RegressionTest")]
[PrebuildSetup("Unity.AI.Navigation.Tests." + nameof(SimpleScene2PlanesNavigationSetup))]
[PostBuildCleanup("Unity.AI.Navigation.Tests." + nameof(SimpleScene2PlanesNavigationSetup))]
class AgentVelocityTestAfterOffMeshLink : OffMeshLinkTestBase
{
readonly string k_SceneName = "OffMeshLinkTwoPlanesScene";
[UnitySetUp]
public IEnumerator UnitySetUp()
{
yield return SceneManager.LoadSceneAsync(k_SceneName, LoadSceneMode.Additive);
yield return null;
SceneManager.SetActiveScene(SceneManager.GetSceneByName(k_SceneName));
}
[UnityTest]
[UnityPlatform(exclude = new[] { RuntimePlatform.OSXServer, RuntimePlatform.WindowsServer, RuntimePlatform.LinuxServer })]
public IEnumerator Agent_AfterTraversingOffMeshLink_HasVelocityAlignedWithTheLink()
{
var link = CreateBiDirectionalLink(true);
m_Agent.transform.position = link.startTransform.position + new Vector3(3, 0, 3);
m_Agent.SetDestination(link.endTransform.position + new Vector3(-3, 0, 3));
yield return null;
while (!m_Agent.isOnOffMeshLink)
yield return null;
while (m_Agent.isOnOffMeshLink)
yield return null;
yield return 0;
var agentMoveDir = m_Agent.velocity;
agentMoveDir.y = 0;
agentMoveDir = agentMoveDir.normalized;
var linkDir = link.endTransform.position - link.startTransform.position;
linkDir.y = 0;
linkDir = linkDir.normalized;
// Get the angle in degrees between the direction vectors.
var angle = Vector3.Angle(linkDir, agentMoveDir);
Assert.That(angle, Is.LessThan(5.0f), "Agent Velocity is not aligned with the off-mesh link.");
}
[UnityTearDown]
public IEnumerator UnityTearDown()
{
yield return SceneManager.UnloadSceneAsync(k_SceneName);
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,88 @@
#if UNITY_EDITOR || UNITY_STANDALONE
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
namespace Unity.AI.Navigation.Tests
{
[TestFixture]
[PrebuildSetup("Unity.AI.Navigation.Tests." + nameof(CurrentNextOffMeshLinkDataSetUp))]
[PostBuildCleanup("Unity.AI.Navigation.Tests." + nameof(CurrentNextOffMeshLinkDataSetUp))]
class CurrentNextOffMeshLinkData
{
const string k_SceneName = "OffMeshLinkTest";
[UnitySetUp]
public IEnumerator UnitySetUp()
{
yield return SceneManager.LoadSceneAsync(k_SceneName, LoadSceneMode.Additive);
yield return null;
SceneManager.SetActiveScene(SceneManager.GetSceneByName(k_SceneName));
}
[UnityTest]
[Explicit("Unstable test")]
public IEnumerator Agent_TraversingOffMeshLink_ReportsCorrectCurrentAndNextLink()
{
var agent = GameObject.Find("Agent").GetComponent<NavMeshAgent>();
var offMeshLink = GameObject.Find("Plane1").GetComponent<NavMeshLink>();
var target = GameObject.Find("Plane2").transform;
Assert.That(offMeshLink, Is.Not.Null, "Didn't find Off-mesh link");
Assert.That(agent, Is.Not.Null, "Didn't find NavMeshAgent");
var destinationSet = agent.SetDestination(target.position);
agent.speed *= 10;
Assert.That(destinationSet, Is.True, "NavMeshAgent's destination position is not set");
// Wait for path calculation
yield return null;
// Before link
while (!agent.isOnOffMeshLink)
{
Assert.That(agent.currentOffMeshLinkData.valid, Is.False, "Before link : agent.currentOffMeshLinkData is valid");
AssertValidOffMeshLinkData(agent.nextOffMeshLinkData, offMeshLink);
yield return null;
}
// On link
while (agent.isOnOffMeshLink)
{
Assert.That(agent.nextOffMeshLinkData.valid, Is.False, "On link : agent.nextOffMeshLinkData is valid");
AssertValidOffMeshLinkData(agent.currentOffMeshLinkData, offMeshLink);
yield return null;
}
// After link
Assert.That(agent.currentOffMeshLinkData.valid, Is.False, "After link : agent.currentOffMeshLinkData is valid");
Assert.That(agent.nextOffMeshLinkData.valid, Is.False, "After link : agent.nextOffMeshLinkData is valid");
}
[UnityTearDown]
public IEnumerator UnityTearDown()
{
yield return SceneManager.UnloadSceneAsync(k_SceneName);
}
static void AssertValidOffMeshLinkData(OffMeshLinkData offMeshLinkData, NavMeshLink offMeshLink)
{
// Double check to avoid spamming success in log-file (decreasing tests performance)
Assert.That(offMeshLinkData.valid, Is.True, "OffMeshLinkData should be valid.");
Assert.That(offMeshLinkData.activated, Is.True, "OffMeshLinkData should be activated.");
Assert.That(offMeshLinkData.linkType, Is.EqualTo(OffMeshLinkType.LinkTypeManual), "OffMeshLinkData's linkType should be Manual.");
Assert.That(offMeshLinkData.owner, Is.EqualTo(offMeshLink), "OffMeshLinkData should reference the NavMeshLink in the scene as the owner object.");
#pragma warning disable CS0618
Assert.That(offMeshLinkData.offMeshLink, Is.Null, "OffMeshLinkData should not reference any legacy OffMeshLink in the scene.");
#pragma warning restore CS0618
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,77 @@
#if UNITY_EDITOR || UNITY_STANDALONE
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
namespace Unity.AI.Navigation.Tests
{
[TestFixture]
[PrebuildSetup("Unity.AI.Navigation.Tests." + nameof(SimpleScene2PlanesNavigationSetup))]
[PostBuildCleanup("Unity.AI.Navigation.Tests." + nameof(SimpleScene2PlanesNavigationSetup))]
class OffMeshLinkGetSetNavMeshArea : OffMeshLinkTestBase
{
int m_AreaMask;
NavMeshLink m_Link;
readonly string k_SceneName = "OffMeshLinkTwoPlanesScene";
[UnitySetUp]
public IEnumerator UnitySetUp()
{
yield return SceneManager.LoadSceneAsync(k_SceneName, LoadSceneMode.Additive);
yield return null;
SceneManager.SetActiveScene(SceneManager.GetSceneByName(k_SceneName));
}
[UnityTest]
[UnityPlatform(exclude = new[] { RuntimePlatform.OSXServer, RuntimePlatform.WindowsServer, RuntimePlatform.LinuxServer })]
public IEnumerator OffMeshLink_WithCustomArea_AllowsThroughOnlyPathsWithMatchingMasks()
{
m_Link = CreateBiDirectionalLink(true);
yield return null;
var defaultArea = NavMesh.GetAreaFromName("Walkable");
var jumpArea = NavMesh.GetAreaFromName("Jump");
Assume.That(m_Link.area, Is.EqualTo(defaultArea), "Unexpected NavMesh area for NavMeshLink");
// Check we can pass 'default' with 'default' mask
m_AreaMask = 1 << defaultArea;
VerifyAreaPassing(true);
// Change oml area to 'jump'
m_Link.area = jumpArea;
Assume.That(m_Link.area, Is.EqualTo(jumpArea), "Unexpected NavMesh area for NavMeshLink");
// Check we cannot pass 'jump' with 'default' mask
VerifyAreaPassing(false);
// Check we can pass 'jump' with 'default' + 'jump' mask
m_AreaMask |= 1 << jumpArea;
VerifyAreaPassing(true);
}
void VerifyAreaPassing(bool expectToPass)
{
var path = new NavMeshPath();
NavMesh.CalculatePath(m_PlaneStart.position, m_PlaneEnd.position, m_AreaMask, path);
if (expectToPass)
Assert.That(path.status, Is.EqualTo(NavMeshPathStatus.PathComplete),
"Expected complete path; with NavMesh area mask " + m_AreaMask + " when NavMeshLink area is " + m_Link.area);
else
Assert.That(path.status, Is.EqualTo(NavMeshPathStatus.PathPartial),
"Expected partial path; with NavMesh area mask " + m_AreaMask + " when NavMeshLink area is " + m_Link.area);
}
[UnityTearDown]
public IEnumerator UnityTearDown()
{
yield return SceneManager.UnloadSceneAsync(k_SceneName);
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,85 @@
#if UNITY_EDITOR || UNITY_STANDALONE
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
namespace Unity.AI.Navigation.Tests
{
[TestFixture]
[PrebuildSetup("Unity.AI.Navigation.Tests." + nameof(SimpleScene2PlanesNavigationSetup))]
[PostBuildCleanup("Unity.AI.Navigation.Tests." + nameof(SimpleScene2PlanesNavigationSetup))]
class OffMeshLinkMultipleAddComponent
{
const string k_SceneName = "OffMeshLinkTwoPlanesScene";
GameObject m_LinkGO;
[UnitySetUp]
public IEnumerator UnitySetUp()
{
yield return SceneManager.LoadSceneAsync(k_SceneName, LoadSceneMode.Additive);
yield return null;
SceneManager.SetActiveScene(SceneManager.GetSceneByName(k_SceneName));
m_LinkGO = new GameObject("OffMeshLinkMultipleAddComponent");
}
[Test]
[UnityPlatform(exclude = new[] { RuntimePlatform.OSXServer, RuntimePlatform.WindowsServer, RuntimePlatform.LinuxServer })]
public void OffMeshLink_WhenMultipleAddedToGameObject_AreAllUsable()
{
var a = GameObject.Find("plane1").GetComponent<Transform>();
var b = GameObject.Find("plane2").GetComponent<Transform>();
Assert.That(a, Is.Not.Null, "Plane1 is missing.");
Assert.That(b, Is.Not.Null, "Plane2 is missing.");
var pathAB = new NavMeshPath();
var pathBA = new NavMeshPath();
var foundAB = NavMesh.CalculatePath(a.position, b.position, -1, pathAB);
var foundBA = NavMesh.CalculatePath(b.position, a.position, -1, pathBA);
Assert.That(foundAB, Is.True, "Found unexpected path A->B.");
Assert.That(foundBA, Is.True, "Found unexpected path B->A.");
// Create setup where one GO has two OffMeshLinks with 'Bi Directional' set to false
AddOneWayLink(a, b);
AddOneWayLink(b, a);
// Tests that path a->b and b->a are valid and have same end-points (mirrored).
foundAB = NavMesh.CalculatePath(a.position, b.position, -1, pathAB);
foundBA = NavMesh.CalculatePath(b.position, a.position, -1, pathBA);
Assert.That(foundAB, Is.True, "No path from A->B");
Assert.That(foundBA, Is.True, "No path from B->A");
var d1 = Vector3.Distance(pathAB.corners[0], pathBA.corners[pathBA.corners.Length - 1]);
var d2 = Vector3.Distance(pathAB.corners[pathAB.corners.Length - 1], pathBA.corners[0]);
Assert.That(d1, Is.EqualTo(0.0f).Within(1e-5f), "Endpoint mismatch: A start -> B end.");
Assert.That(d2, Is.EqualTo(0.0f).Within(1e-5f), "Endpoint mismatch: B start -> A end.");
}
void AddOneWayLink(Transform start, Transform end)
{
var offMeshLink = m_LinkGO.AddComponent<NavMeshLink>();
Assert.That(offMeshLink, Is.Not.Null, "Failed to create NavMeshLink.");
offMeshLink.bidirectional = false;
offMeshLink.startTransform = start;
offMeshLink.endTransform = end;
// we modified the endpoint references above - now explicitly update positions.
offMeshLink.UpdateLink();
}
[UnityTearDown]
public IEnumerator UnityTearDown()
{
Object.DestroyImmediate(m_LinkGO);
yield return SceneManager.UnloadSceneAsync(k_SceneName);
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,41 @@
#if UNITY_EDITOR || UNITY_STANDALONE
using NUnit.Framework;
using UnityEngine;
using UnityEngine.AI;
namespace Unity.AI.Navigation.Tests
{
class OffMeshLinkTestBase
{
protected Transform m_PlaneStart;
protected Transform m_PlaneEnd;
protected NavMeshAgent m_Agent;
public NavMeshLink CreateBiDirectionalLink(bool autoUpdatePositions)
{
var planeStartGO = GameObject.Find("plane1");
Assert.That(planeStartGO, Is.Not.Null, "Didn't find gameobject plane1");
m_PlaneStart = planeStartGO.transform;
var planeEndGO = GameObject.Find("plane2");
Assert.That(planeEndGO, Is.Not.Null, "Didn't find gameobject plane2");
m_PlaneEnd = planeEndGO.transform;
var agentGo = GameObject.Find("Agent");
Assert.That(agentGo, Is.Not.Null, "Didn't find gameobject Agent");
m_Agent = agentGo.GetComponent<NavMeshAgent>();
Assert.That(m_Agent, Is.Not.Null, "Didn't find component NavMeshAgent in gameobject Agent");
m_Agent.speed *= 10.0f;
m_Agent.acceleration *= 10.0f;
var linkGO = new GameObject("link");
var link = linkGO.AddComponent<NavMeshLink>();
Assert.That(link, Is.Not.Null, "Unable to add NavMeshLink component.");
link.startTransform = m_PlaneStart;
link.endTransform = m_PlaneEnd;
link.autoUpdate = autoUpdatePositions;
return link;
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 028144d6018e97b4eabdb685c9fc01a0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,54 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.SceneManagement;
#endif
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;
using Utils = UnityEngine.TestTools.Utils.Utils;
#pragma warning disable CS0618 // UnityEditor.AI.NavMeshBuilder is necessary in this implementation
namespace Unity.AI.Navigation.Tests
{
class CurrentNextOffMeshLinkDataSetUp : PrebuiltSceneSetup
{
protected override string GetSceneFile()
{
return "OffMeshLinkTest.unity";
}
protected override void SceneSetup()
{
#if UNITY_EDITOR
var myScene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Additive);
SceneManager.SetActiveScene(myScene);
var plane1 = Utils.CreatePrimitive(PrimitiveType.Plane);
GameObjectUtility.SetStaticEditorFlags(plane1, StaticEditorFlags.NavigationStatic);
plane1.name = "Plane1";
plane1.transform.position = Vector3.zero;
var plane2 = Utils.CreatePrimitive(PrimitiveType.Plane);
GameObjectUtility.SetStaticEditorFlags(plane2, StaticEditorFlags.NavigationStatic);
plane2.name = "Plane2";
plane2.transform.position = new Vector3(0, 0, 15);
var offMeshLink = plane1.AddComponent<NavMeshLink>();
offMeshLink.startTransform = plane1.transform;
offMeshLink.endTransform = plane2.transform;
var cube = Utils.CreatePrimitive(PrimitiveType.Cube);
cube.transform.position = new Vector3(0, 0, -4);
cube.name = "Agent";
cube.AddComponent<NavMeshAgent>();
EditorSceneManager.SaveScene(SceneManager.GetActiveScene(), pathToTestScene);
UnityEditor.AI.NavMeshBuilder.BuildNavMesh();
EditorSceneManager.SaveScene(SceneManager.GetActiveScene(), pathToTestScene);
EditorSceneManager.CloseScene(myScene, true);
UnityEditor.AI.NavMeshBuilder.ClearAllNavMeshes();
#endif
}
}
}

View File

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

View File

@@ -0,0 +1,58 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine.TestTools;
namespace Unity.AI.Navigation.Tests
{
abstract class PrebuiltSceneSetup : IPrebuildSetup, IPostBuildCleanup
{
const string k_RootDir = "Assets";
const string k_TestDir = "TmpScenes";
string testDirectory { get; set; } = "";
protected string pathToTestScene { get; private set; } = "";
protected abstract string GetSceneFile();
protected abstract void SceneSetup();
public void Setup()
{
#if UNITY_EDITOR
testDirectory = Path.Combine(k_RootDir, k_TestDir);
pathToTestScene = Path.Combine(testDirectory, GetSceneFile());
AssetDatabase.Refresh();
if (!AssetDatabase.IsValidFolder(testDirectory))
testDirectory = AssetDatabase.GUIDToAssetPath(AssetDatabase.CreateFolder(k_RootDir, k_TestDir));
AssetDatabase.Refresh();
SceneSetup();
var editorBuildSettingsScenes = new List<EditorBuildSettingsScene>(EditorBuildSettings.scenes)
{
new EditorBuildSettingsScene(pathToTestScene, true)
};
EditorBuildSettings.scenes = editorBuildSettingsScenes.ToArray();
#endif
}
public void Cleanup()
{
#if UNITY_EDITOR
AssetDatabase.Refresh();
testDirectory = Path.Combine(k_RootDir, k_TestDir);
pathToTestScene = Path.Combine(testDirectory, GetSceneFile());
var baseSceneGuidTxt = AssetDatabase.AssetPathToGUID(pathToTestScene);
if (AssetDatabase.IsValidFolder(testDirectory))
AssetDatabase.DeleteAsset(testDirectory);
if (GUID.TryParse(baseSceneGuidTxt, out var sceneGuid))
EditorBuildSettings.scenes = EditorBuildSettings.scenes.Where(scene => scene.guid != sceneGuid).ToArray();
#endif
}
}
}

View File

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

View File

@@ -0,0 +1,50 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.SceneManagement;
#endif
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools.Utils;
#pragma warning disable CS0618 // UnityEditor.AI.NavMeshBuilder is necessary in this implementation
namespace Unity.AI.Navigation.Tests
{
class SimpleScene2PlanesNavigationSetup : PrebuiltSceneSetup
{
protected override string GetSceneFile()
{
return "OffMeshLinkTwoPlanesScene.unity";
}
protected override void SceneSetup()
{
#if UNITY_EDITOR
var myScene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Additive);
SceneManager.SetActiveScene(myScene);
var plane1 = Utils.CreatePrimitive(PrimitiveType.Plane);
plane1.transform.position = new Vector3(10f, 0f, 0f);
plane1.name = "plane1";
GameObjectUtility.SetStaticEditorFlags(plane1, StaticEditorFlags.NavigationStatic);
var plane2 = Utils.CreatePrimitive(PrimitiveType.Plane);
plane2.transform.position = new Vector3(25f, 0f, 0f);
plane2.name = "plane2";
GameObjectUtility.SetStaticEditorFlags(plane2, StaticEditorFlags.NavigationStatic);
var capsule = Utils.CreatePrimitive(PrimitiveType.Capsule);
capsule.name = "Agent";
capsule.transform.position = new Vector3(6, 0, 0);
capsule.AddComponent<NavMeshAgent>();
EditorSceneManager.SaveScene(SceneManager.GetActiveScene(), pathToTestScene);
UnityEditor.AI.NavMeshBuilder.BuildNavMesh();
EditorSceneManager.SaveScene(SceneManager.GetActiveScene(), pathToTestScene);
EditorSceneManager.CloseScene(myScene, true);
UnityEditor.AI.NavMeshBuilder.ClearAllNavMeshes();
#endif
}
}
}

View File

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

View File

@@ -0,0 +1,21 @@
{
"name": "Unity.AI.Navigation.LegacyOffMeshLink.Tests",
"rootNamespace": "",
"references": [
"GUID:8c4dd21966739024fbd72155091d199e",
"GUID:27619889b8ba8c24980f49ee34dbb44a"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View File

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

View File

@@ -0,0 +1,28 @@
{
"name": "Unity.AI.Navigation.Tests",
"rootNamespace": "",
"references": [
"GUID:27619889b8ba8c24980f49ee34dbb44a",
"GUID:0acc523941302664db1f4e527237feb3",
"GUID:8c4dd21966739024fbd72155091d199e"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [
{
"name": "com.unity.modules.physics",
"expression": "1.0.0",
"define": "NMC_CAN_ACCESS_PHYSICS"
}
],
"noEngineReferences": false
}

View File

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