#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(); 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().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().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