first commit
This commit is contained in:
@@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a2ea6cc04d4a4333b94b04c4d51c56c
|
||||
@@ -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
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45e898f1334e740678c21331ac30d746
|
||||
timeCreated: 1490606318
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.AI.Navigation.Tests
|
||||
{
|
||||
[DefaultExecutionOrder(-1)]
|
||||
class NavMeshSurfaceBuildFromAwake : MonoBehaviour
|
||||
{
|
||||
public NavMeshSurface surface;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
surface.BuildNavMesh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e6be2106b2f72df4199763945ec1f6ec
|
||||
@@ -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
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 264ca61ae1b6e4c16bcfc55f84300402
|
||||
timeCreated: 1490606318
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9fe5cff05af44c0fb71a8dcc44efc41
|
||||
timeCreated: 1490606318
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5d873c779b014234ba92f3cb7476da6
|
||||
timeCreated: 1490606318
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 925111c157b314873b97f89e0f03d570
|
||||
timeCreated: 1490606318
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c10f4966eb108848acf7461aaf6057e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f48814e34f5bd94eb57d5a64f7d6d5f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca27eb55b0331d042a94fe7f8899234c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ebd8eb82fbc3924e92211a0c85dfa02
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 940906a00341424438da6b0e6ef377de
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8e30eff1e26b3b428d7ae3ce3158107
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9956f614ad36a614788c97144e44730f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6066975671f8b09468b3412d411861c5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 028144d6018e97b4eabdb685c9fc01a0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a0a2560470c5b542813d7c93f1b3261
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57568e502950ef142a879100dfa67153
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5110d4284121dd4481bffe2647ad892
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68d7ff144262c9148888e665efa8692c
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 455cd750f394b1c41b963b3335eae29c
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user