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

290 lines
14 KiB
C#
Raw Permalink 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("PrefabsWithNavMeshComponents")]
class NavMeshSurfaceInPrefabVariantTests
{
const string k_AutoSaveKey = "AutoSave";
const string k_ParentFolder = "Assets";
const string k_TempFolderName = "TempPrefabVariants";
static readonly string k_TempFolder = Path.Combine(k_ParentFolder, k_TempFolderName);
const int k_GrayArea = 7;
const int k_BrownArea = 10;
const int k_RedArea = 18;
const int k_OrangeArea = 26;
const int k_YellowArea = 30;
const int k_PrefabDefaultArea = k_YellowArea;
static bool s_EnterPlayModeOptionsEnabled;
static EnterPlayModeOptions s_EnterPlayModeOptions;
[SerializeField]
string m_PrefabPath;
[SerializeField]
string m_PrefabVariantPath;
[SerializeField]
string m_PreviousScenePath;
[SerializeField]
string m_TempScenePath;
[SerializeField]
int m_TestCounter;
#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, "NavMeshSurfacePrefabVariantTestsScene.unity");
var tempScene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Single);
EditorSceneManager.SaveScene(tempScene, m_TempScenePath);
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
}
[UnitySetUp]
public IEnumerator SetupVariantOfPrefabWithNavMesh()
{
if (EditorApplication.isPlaying)
yield break;
var plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
plane.name = "NavMeshSurfacePrefab" + (++m_TestCounter);
var surface = plane.AddComponent<NavMeshSurface>();
surface.collectObjects = CollectObjects.Children;
m_PrefabPath = Path.Combine(k_TempFolder, plane.name + ".prefab");
m_PrefabVariantPath = Path.Combine(k_TempFolder, plane.name + "Variant.prefab");
var planePrefab = PrefabUtility.SaveAsPrefabAsset(plane, m_PrefabPath);
Object.DestroyImmediate(plane);
AssetDatabase.OpenAsset(planePrefab);
var theOriginalPrefabStage = PrefabStageUtility.GetCurrentPrefabStage();
var theOriginalPrefabSurface = theOriginalPrefabStage.prefabContentsRoot.GetComponent<NavMeshSurface>();
yield return TestUtility.BakeNavMeshAsync(theOriginalPrefabSurface, k_PrefabDefaultArea);
PrefabSavingUtil.SavePrefab(theOriginalPrefabStage);
StageUtility.GoToMainStage();
var instanceForVariant = PrefabUtility.InstantiatePrefab(planePrefab) as GameObject;
PrefabUtility.SaveAsPrefabAsset(instanceForVariant, m_PrefabVariantPath);
instanceForVariant!.name += "_Saved";
TestUtility.EliminateFromScene(ref instanceForVariant, k_KeepSceneObjects);
NavMesh.RemoveAllNavMeshData();
yield return null;
}
[UnityTearDown]
public IEnumerator TearDown()
{
if (EditorApplication.isPlaying)
yield return new ExitPlayMode();
StageUtility.GoToMainStage();
yield return null;
}
[UnityTest]
public IEnumerator NavMeshSurfacePrefabVariant_WhenFreshAndRebaked_ParentAssetUnchanged(
[Values(RunMode.EditMode, RunMode.PlayMode)]
RunMode runMode)
{
var theOriginalPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(m_PrefabPath);
AssetDatabase.OpenAsset(theOriginalPrefab);
if (runMode == RunMode.PlayMode)
yield return new EnterPlayMode();
var theOriginalPrefabStage = PrefabStageUtility.GetCurrentPrefabStage();
var theOriginalPrefabSurface = theOriginalPrefabStage.prefabContentsRoot.GetComponent<NavMeshSurface>();
var theOriginalPrefabNavMeshData = theOriginalPrefabSurface.navMeshData;
var theOriginalPrefabAssetPath = AssetDatabase.GetAssetPath(theOriginalPrefabSurface.navMeshData);
Assert.IsTrue(theOriginalPrefabNavMeshData != null, "Original prefab must have some NavMeshData.");
Assert.IsTrue(File.Exists(theOriginalPrefabAssetPath), "NavMeshData file must exist for the original prefab. ({0})", theOriginalPrefabAssetPath);
var prefabVariant = AssetDatabase.LoadAssetAtPath<GameObject>(m_PrefabVariantPath);
AssetDatabase.OpenAsset(prefabVariant);
var prefabVariantStage = PrefabStageUtility.GetCurrentPrefabStage();
var prefabVariantSurface = prefabVariantStage.prefabContentsRoot.GetComponent<NavMeshSurface>();
var initialVariantNavMeshData = prefabVariantSurface.navMeshData;
var initialVariantAssetPath = AssetDatabase.GetAssetPath(prefabVariantSurface.navMeshData);
Assert.AreEqual(theOriginalPrefabNavMeshData, initialVariantNavMeshData, "Fresh variant must have the same NavMeshData as the original prefab.");
Assert.IsTrue(initialVariantNavMeshData != null, "Prefab must have some NavMeshData.");
Assert.IsTrue(File.Exists(initialVariantAssetPath), "NavMeshData file must exist. ({0})", initialVariantAssetPath);
yield return TestUtility.BakeNavMeshAsync(prefabVariantSurface, k_GrayArea);
Assert.IsTrue(initialVariantNavMeshData != null, "The initial NavMeshData (from original prefab) must still exist immediately after prefab variant re-bake.");
Assert.IsTrue(File.Exists(initialVariantAssetPath), "The initial NavMeshData file (from original prefab) must exist after prefab variant re-bake. ({0})", initialVariantAssetPath);
Assert.IsTrue(prefabVariantSurface.navMeshData != null, "NavMeshSurface must have NavMeshData after baking.");
var unsavedRebakedNavMeshData = prefabVariantSurface.navMeshData;
yield return TestUtility.BakeNavMeshAsync(prefabVariantSurface, k_BrownArea);
Assert.IsTrue(unsavedRebakedNavMeshData == null, "An unsaved NavMeshData should not exist after a re-bake.");
Assert.IsTrue(prefabVariantSurface.navMeshData != null, "NavMeshSurface must have NavMeshData after baking.");
PrefabSavingUtil.SavePrefab(prefabVariantStage);
var theNewVariantNavMeshData = prefabVariantSurface.navMeshData;
var theNewVariantAssetPath = AssetDatabase.GetAssetPath(theNewVariantNavMeshData);
Assert.IsTrue(File.Exists(theNewVariantAssetPath), "Variant's own NavMeshData exists in a file after saving. ({0})", theNewVariantAssetPath);
Assert.IsTrue(File.Exists(theOriginalPrefabAssetPath), "NavMeshData file of the original prefab still exists after saving the variant. ({0})", theOriginalPrefabAssetPath);
Assert.IsTrue(theOriginalPrefabNavMeshData != null, "Original prefab must still have NavMeshData.");
StageUtility.GoToMainStage();
yield return null;
if (EditorApplication.isPlaying)
yield return new ExitPlayMode();
}
[UnityTest]
public IEnumerator NavMeshSurfacePrefabVariant_WhenCustomizedAndRebaked_OldAssetDiscardedAndParentAssetUnchanged(
[Values(RunMode.EditMode, RunMode.PlayMode)]
RunMode runMode)
{
var prefabVariant = AssetDatabase.LoadAssetAtPath<GameObject>(m_PrefabVariantPath);
var theOriginalPrefabPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefabVariant);
var theOriginalPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(theOriginalPrefabPath);
AssetDatabase.OpenAsset(theOriginalPrefab);
if (runMode == RunMode.PlayMode)
yield return new EnterPlayMode();
var theOriginalPrefabStage = PrefabStageUtility.GetCurrentPrefabStage();
var theOriginalPrefabSurface = theOriginalPrefabStage.prefabContentsRoot.GetComponent<NavMeshSurface>();
var theOriginalPrefabNavMeshData = theOriginalPrefabSurface.navMeshData;
var theOriginalPrefabAssetPath = AssetDatabase.GetAssetPath(theOriginalPrefabSurface.navMeshData);
Assert.IsTrue(theOriginalPrefabNavMeshData != null, "Original prefab must have some NavMeshData.");
Assert.IsTrue(File.Exists(theOriginalPrefabAssetPath), "NavMeshData file must exist for the original prefab. ({0})", theOriginalPrefabAssetPath);
AssetDatabase.OpenAsset(prefabVariant);
var prefabVariantStage = PrefabStageUtility.GetCurrentPrefabStage();
var prefabVariantSurface = prefabVariantStage.prefabContentsRoot.GetComponent<NavMeshSurface>();
yield return TestUtility.BakeNavMeshAsync(prefabVariantSurface, k_GrayArea);
PrefabSavingUtil.SavePrefab(prefabVariantStage);
var modifiedVariantNavMeshData = prefabVariantSurface.navMeshData;
var modifiedVariantAssetPath = AssetDatabase.GetAssetPath(prefabVariantSurface.navMeshData);
Assert.IsTrue(modifiedVariantNavMeshData != null, "Prefab must have some NavMeshData.");
Assert.IsTrue(File.Exists(modifiedVariantAssetPath), "NavMeshData file for modifier variant must exist. ({0})", modifiedVariantAssetPath);
Assert.AreNotEqual(theOriginalPrefabNavMeshData, modifiedVariantNavMeshData, "Modified variant must have a NavMeshData different than that of the original prefab.");
yield return TestUtility.BakeNavMeshAsync(prefabVariantSurface, k_OrangeArea);
Assert.IsTrue(modifiedVariantNavMeshData != null, "The initial NavMeshData of a modified variant must still exist immediately after prefab variant re-bake.");
Assert.IsTrue(File.Exists(modifiedVariantAssetPath), "The initial NavMeshData file of a modified variant must exist after prefab variant re-bake. ({0})", modifiedVariantAssetPath);
Assert.IsTrue(prefabVariantSurface.navMeshData != null, "NavMeshSurface must have NavMeshData after baking.");
var unsavedRebakedNavMeshData = prefabVariantSurface.navMeshData;
yield return TestUtility.BakeNavMeshAsync(prefabVariantSurface, k_RedArea);
Assert.IsTrue(unsavedRebakedNavMeshData == null, "An unsaved NavMeshData should not exist after a re-bake.");
Assert.IsTrue(prefabVariantSurface.navMeshData != null, "NavMeshSurface must have NavMeshData after baking.");
PrefabSavingUtil.SavePrefab(prefabVariantStage);
var theNewVariantNavMeshData = prefabVariantSurface.navMeshData;
var theNewVariantAssetPath = AssetDatabase.GetAssetPath(theNewVariantNavMeshData);
if (EditorApplication.isPlaying)
{
Assert.IsTrue(modifiedVariantNavMeshData != null, "Playmode: Initial NavMeshData of the modified variant must still exist until the end of playmode.");
Assert.IsTrue(File.Exists(modifiedVariantAssetPath), "Playmode: Initial NavMeshData file of the modified and saved variant must still exist after saving the variant during playmode. ({0})", modifiedVariantAssetPath);
}
else
{
Assert.IsTrue(modifiedVariantNavMeshData == null, "Editmode: Initial NavMeshData of the modified variant must no longer exist after saving the variant.");
// This code is still reachable because modifiedVariantNavMeshData has been affected by BakeNavMeshAsync()
Assert.IsFalse(File.Exists(modifiedVariantAssetPath), "Editmode: Initial NavMeshData file of the modified and saved variant must no longer exist after saving the variant. ({0})", modifiedVariantAssetPath);
}
Assert.IsTrue(File.Exists(theNewVariantAssetPath), "Variant's own NavMeshData exists in a file after saving. ({0})", theNewVariantAssetPath);
Assert.IsTrue(File.Exists(theOriginalPrefabAssetPath), "NavMeshData file of the original prefab still exists after saving the variant. ({0})", theOriginalPrefabAssetPath);
Assert.AreNotEqual(theOriginalPrefabNavMeshData, theNewVariantNavMeshData, "Re-baked modified variant must have a NavMeshData different than that of the original prefab.");
StageUtility.GoToMainStage();
yield return null;
if (EditorApplication.isPlaying)
yield return new ExitPlayMode();
}
}
}
#endif