UnityGame/Library/PackageCache/com.unity.ai.navigation/Tests/Editor/NavMeshModifierVolumeInPrefabTests.cs

279 lines
12 KiB
C#
Raw Normal View History

2024-10-27 10:53:47 +03:00
#if UNITY_EDITOR || UNITY_STANDALONE
//#define KEEP_ARTIFACTS_FOR_INSPECTION
using System.Collections;
using System.IO;
using NUnit.Framework;
using UnityEditor;
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());
}
}
}
#endif