123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- //#define KEEP_ARTIFACTS_FOR_INSPECTION
-
- using System.Collections;
- using System.IO;
- using NUnit.Framework;
- using UnityEditor;
- #if !UNITY_2021_2_OR_NEWER
- using UnityEditor.Experimental.SceneManagement;
- #endif
- using UnityEditor.SceneManagement;
- using UnityEngine;
- using UnityEngine.AI;
- using UnityEngine.SceneManagement;
- using UnityEngine.TestTools;
- using Object = UnityEngine.Object;
-
- namespace Unity.AI.Navigation.Editor.Tests
- {
- [Category("PrefabsWithNavMeshModifierVolume")]
- class NavMeshModifierVolumeInPrefabTests
- {
- const string k_AutoSaveKey = "AutoSave";
- const string k_ParentFolder = "Assets";
- const string k_TempFolderName = "TempPrefabAndModifiers";
- static readonly string k_TempFolder = Path.Combine(k_ParentFolder, k_TempFolderName);
-
- const int k_PinkArea = 3;
- const int k_GreenArea = 4;
- const int k_RedArea = 18;
-
- const int k_PrefabDefaultArea = k_GreenArea;
-
- static readonly NavMeshQueryFilter k_QueryAnyArea = new() { agentTypeID = 0, areaMask = NavMesh.AllAreas };
-
- static bool s_EnterPlayModeOptionsEnabled;
- static EnterPlayModeOptions s_EnterPlayModeOptions;
-
- [SerializeField]
- string m_PrefabPath;
- [SerializeField]
- string m_PreviousScenePath;
- [SerializeField]
- string m_TempScenePath;
- [SerializeField]
- int m_TestCounter;
- [SerializeField]
- GameObject m_SurfaceInstance;
- [SerializeField]
- GameObject m_ModVolInstance;
-
- #if KEEP_ARTIFACTS_FOR_INSPECTION
- const bool k_KeepSceneObjects = true;
- #else
- const bool k_KeepSceneObjects = false;
- #endif
- [OneTimeSetUp]
- public void OneTimeSetup()
- {
- if (EditorApplication.isPlaying)
- return;
-
- AssetDatabase.DeleteAsset(k_TempFolder);
- var folderGUID = AssetDatabase.CreateFolder(k_ParentFolder, k_TempFolderName);
- Assume.That(folderGUID, Is.Not.Empty);
-
- SessionState.SetBool(k_AutoSaveKey, PrefabStageAutoSavingUtil.GetPrefabStageAutoSave());
- PrefabStageAutoSavingUtil.SetPrefabStageAutoSave(false);
- StageUtility.GoToMainStage();
-
- m_PreviousScenePath = SceneManager.GetActiveScene().path;
- m_TempScenePath = Path.Combine(k_TempFolder, "NavMeshModifierVolumePrefabTestsScene.unity");
- var tempScene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Single);
- EditorSceneManager.SaveScene(tempScene, m_TempScenePath);
- AssetDatabase.Refresh();
- EditorSceneManager.OpenScene(m_TempScenePath);
-
- s_EnterPlayModeOptionsEnabled = EditorSettings.enterPlayModeOptionsEnabled;
- s_EnterPlayModeOptions = EditorSettings.enterPlayModeOptions;
-
- EditorSettings.enterPlayModeOptionsEnabled = true;
- EditorSettings.enterPlayModeOptions = EnterPlayModeOptions.DisableDomainReload | EnterPlayModeOptions.DisableSceneReload;
- }
-
- [OneTimeTearDown]
- public void OneTimeTearDown()
- {
- if (EditorApplication.isPlaying)
- return;
-
- PrefabStageAutoSavingUtil.SetPrefabStageAutoSave(SessionState.GetBool(k_AutoSaveKey, PrefabStageAutoSavingUtil.GetPrefabStageAutoSave()));
- StageUtility.GoToMainStage();
-
- EditorSceneManager.SaveScene(SceneManager.GetActiveScene());
-
- if (string.IsNullOrEmpty(m_PreviousScenePath))
- EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Single);
-
- EditorSettings.enterPlayModeOptionsEnabled = s_EnterPlayModeOptionsEnabled;
- EditorSettings.enterPlayModeOptions = s_EnterPlayModeOptions;
-
- #if !KEEP_ARTIFACTS_FOR_INSPECTION
- AssetDatabase.DeleteAsset(k_TempFolder);
- #endif
- }
-
- [SetUp]
- public void SetupNewPrefabWithEmptyNavMesh()
- {
- if (EditorApplication.isPlaying)
- return;
-
- var plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
- plane.name = "SurfaceSeekingModVol" + ++m_TestCounter + "Prefab";
- var surface = plane.AddComponent<NavMeshSurface>();
- surface.collectObjects = CollectObjects.All;
-
- m_PrefabPath = Path.Combine(k_TempFolder, plane.name + ".prefab");
- PrefabUtility.SaveAsPrefabAsset(plane, m_PrefabPath);
- Object.DestroyImmediate(plane);
-
- NavMesh.RemoveAllNavMeshData();
- }
-
- [UnityTearDown]
- public IEnumerator TearDownAndReturnToMainStage()
- {
- if (EditorApplication.isPlaying)
- yield return new ExitPlayMode();
-
- StageUtility.GoToMainStage();
-
- TestUtility.EliminateFromScene(ref m_ModVolInstance, k_KeepSceneObjects);
- TestUtility.EliminateFromScene(ref m_SurfaceInstance, k_KeepSceneObjects);
-
- yield return null;
- }
-
- [UnityTest]
- public IEnumerator ModifierVolume_WhenInsidePrefabMode_ModifiesTheNavMeshInPrefab(
- [Values(RunMode.EditMode, RunMode.PlayMode)]
- RunMode runMode)
- {
- var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(m_PrefabPath);
- m_SurfaceInstance = TestUtility.InstantiatePrefab(prefab, "SurfaceSeekingModVol" + m_TestCounter + "PrefabInstance");
-
- NavMesh.SamplePosition(Vector3.zero, out var hit, 0.1f, k_QueryAnyArea);
- Assume.That(hit.hit, Is.False, "Prefab should not have a NavMesh in the beginning.");
-
- if (runMode == RunMode.PlayMode)
- {
- yield return new EnterPlayMode();
- prefab = AssetDatabase.LoadAssetAtPath<GameObject>(m_PrefabPath);
- }
-
- AssetDatabase.OpenAsset(prefab);
- var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
- var prefabSurface = prefabStage.prefabContentsRoot.GetComponent<NavMeshSurface>();
- var modifierVolume = prefabStage.prefabContentsRoot.AddComponent<NavMeshModifierVolume>();
- modifierVolume.area = k_RedArea;
- modifierVolume.center = Vector3.zero;
- modifierVolume.size = Vector3.one;
- yield return TestUtility.BakeNavMeshAsync(prefabSurface, k_PrefabDefaultArea);
- PrefabSavingUtil.SavePrefab(prefabStage);
- StageUtility.GoToMainStage();
-
- if (EditorApplication.isPlaying)
- yield return new ExitPlayMode();
-
- NavMesh.SamplePosition(Vector3.zero, out var hitCenter, 0.1f, k_QueryAnyArea);
- Assume.That(hitCenter.hit, Is.True, "A NavMesh should have been baked in the center of the prefab.");
- Assert.That(hitCenter.mask, Is.EqualTo(1 << k_RedArea),
- "Area type (0x{0:x8}) found in the center should be 0x{1:x8}.", hitCenter.mask, 1 << k_RedArea);
-
- NavMesh.SamplePosition(new Vector3(0.6f, 0, 0.6f), out var hitSides, 0.1f, k_QueryAnyArea);
- Assume.That(hitSides.hit, Is.True, "A NavMesh should have been baked in the outer sides of the prefab.");
- Assert.That(hitSides.mask, Is.EqualTo(1 << k_PrefabDefaultArea),
- "Area type (0x{0:x8}) found on the sides should be 0x{1:x8}.", hitSides.mask, 1 << k_PrefabDefaultArea);
-
- Assert.That(hitCenter.mask, Is.Not.EqualTo(hitSides.mask),
- "Area type (0x{0:x8}) in the center should be different than on the sides.", hitCenter.mask);
-
- EditorSceneManager.SaveScene(SceneManager.GetActiveScene());
- }
-
- [UnityTest]
- public IEnumerator ModifierVolume_WhenInsidePrefabMode_DoesNotAffectTheNavMeshInMainScene(
- [Values(RunMode.EditMode, RunMode.PlayMode)]
- RunMode runMode)
- {
- m_SurfaceInstance = GameObject.CreatePrimitive(PrimitiveType.Plane);
- m_SurfaceInstance.name = "SurfaceOutsidePrefab" + m_TestCounter;
- var mainSceneSurface = m_SurfaceInstance.AddComponent<NavMeshSurface>();
- mainSceneSurface.defaultArea = k_PinkArea;
- mainSceneSurface.agentTypeID = 0;
- mainSceneSurface.collectObjects = CollectObjects.All;
-
- NavMesh.SamplePosition(Vector3.zero, out var hit, 0.1f, k_QueryAnyArea);
- Assume.That(hit.hit, Is.False, "The main scene should not have a NavMesh in the beginning.");
-
- EditorSceneManager.SaveScene(SceneManager.GetActiveScene());
-
- var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(m_PrefabPath);
- AssetDatabase.OpenAsset(prefab);
- var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
- var prefabModVol = prefabStage.prefabContentsRoot.AddComponent<NavMeshModifierVolume>();
- prefabModVol.area = k_PrefabDefaultArea;
- prefabModVol.center = Vector3.zero;
- prefabModVol.size = new Vector3(100, 100, 100);
-
- // Bake the NavMeshSurface from the main scene while the prefab mode is open
- if (runMode == RunMode.PlayMode)
- yield return new EnterPlayMode();
-
- mainSceneSurface = m_SurfaceInstance.GetComponent<NavMeshSurface>();
- prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
-
- yield return TestUtility.BakeNavMeshAsync(mainSceneSurface, mainSceneSurface.defaultArea);
-
- PrefabSavingUtil.SavePrefab(prefabStage);
- if (!EditorApplication.isPlaying)
- EditorSceneManager.SaveScene(SceneManager.GetActiveScene());
- StageUtility.GoToMainStage();
-
- NavMesh.SamplePosition(Vector3.zero, out hit, 0.1f, k_QueryAnyArea);
- Assert.That(hit.hit, Is.True, "A NavMesh should have been baked by the surface in the main scene.");
- Assert.That(hit.mask, Is.EqualTo(1 << mainSceneSurface.defaultArea),
- "NavMesh has the area type 0x{0:x8} instead of the expected 0x{1:x8}.", hit.mask, 1 << mainSceneSurface.defaultArea);
-
- if (EditorApplication.isPlaying)
- yield return new ExitPlayMode();
- }
-
- [UnityTest]
- public IEnumerator ModifierVolume_WhenOutsidePrefabMode_DoesNotAffectTheNavMeshInPrefab(
- [Values(RunMode.EditMode, RunMode.PlayMode)]
- RunMode runMode)
- {
- m_ModVolInstance = new GameObject("ModifierVolumeOutsidePrefab" + m_TestCounter);
- var modifierVolume = m_ModVolInstance.AddComponent<NavMeshModifierVolume>();
- modifierVolume.area = k_RedArea;
- modifierVolume.center = Vector3.zero;
- modifierVolume.size = new Vector3(20, 20, 20);
-
- var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(m_PrefabPath);
- m_SurfaceInstance = TestUtility.InstantiatePrefab(prefab, "SurfaceSeekingModVol" + m_TestCounter + "PrefabInstance");
-
- NavMesh.SamplePosition(Vector3.zero, out var hit, 0.1f, k_QueryAnyArea);
- Assume.That(hit.hit, Is.False, "Prefab should not have a NavMesh in the beginning.");
-
- EditorSceneManager.SaveScene(SceneManager.GetActiveScene());
-
- if (runMode == RunMode.PlayMode)
- {
- yield return new EnterPlayMode();
-
- prefab = AssetDatabase.LoadAssetAtPath<GameObject>(m_PrefabPath);
- }
-
- AssetDatabase.OpenAsset(prefab);
- var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
- var prefabSurface = prefabStage.prefabContentsRoot.GetComponent<NavMeshSurface>();
-
- yield return TestUtility.BakeNavMeshAsync(prefabSurface, k_PrefabDefaultArea);
-
- PrefabSavingUtil.SavePrefab(prefabStage);
- StageUtility.GoToMainStage();
-
- if (EditorApplication.isPlaying)
- yield return new ExitPlayMode();
-
- NavMesh.SamplePosition(Vector3.zero, out hit, 0.1f, k_QueryAnyArea);
- Assume.That(hit.hit, Is.True, "A NavMesh should have been baked in the prefab.");
- Assert.That(hit.mask, Is.EqualTo(1 << k_PrefabDefaultArea),
- "A different area type (0x{0:x8}) was found instead of the expected one (0x{1:x8}).", hit.mask, 1 << k_PrefabDefaultArea);
-
- EditorSceneManager.SaveScene(SceneManager.GetActiveScene());
- }
- }
- }
|