Nessuna descrizione
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

NavMeshSurfaceInPrefabVariantTests.cs 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. //#define KEEP_ARTIFACTS_FOR_INSPECTION
  2. using System.Collections;
  3. using System.IO;
  4. using NUnit.Framework;
  5. using UnityEditor;
  6. #if !UNITY_2021_2_OR_NEWER
  7. using UnityEditor.Experimental.SceneManagement;
  8. #endif
  9. using UnityEditor.SceneManagement;
  10. using UnityEngine;
  11. using UnityEngine.AI;
  12. using UnityEngine.SceneManagement;
  13. using UnityEngine.TestTools;
  14. using Object = UnityEngine.Object;
  15. namespace Unity.AI.Navigation.Editor.Tests
  16. {
  17. [Category("PrefabsWithNavMeshComponents")]
  18. class NavMeshSurfaceInPrefabVariantTests
  19. {
  20. const string k_AutoSaveKey = "AutoSave";
  21. const string k_ParentFolder = "Assets";
  22. const string k_TempFolderName = "TempPrefabVariants";
  23. static readonly string k_TempFolder = Path.Combine(k_ParentFolder, k_TempFolderName);
  24. const int k_GrayArea = 7;
  25. const int k_BrownArea = 10;
  26. const int k_RedArea = 18;
  27. const int k_OrangeArea = 26;
  28. const int k_YellowArea = 30;
  29. const int k_PrefabDefaultArea = k_YellowArea;
  30. static bool s_EnterPlayModeOptionsEnabled;
  31. static EnterPlayModeOptions s_EnterPlayModeOptions;
  32. [SerializeField]
  33. string m_PrefabPath;
  34. [SerializeField]
  35. string m_PrefabVariantPath;
  36. [SerializeField]
  37. string m_PreviousScenePath;
  38. [SerializeField]
  39. string m_TempScenePath;
  40. [SerializeField]
  41. int m_TestCounter;
  42. #if KEEP_ARTIFACTS_FOR_INSPECTION
  43. const bool k_KeepSceneObjects = true;
  44. #else
  45. const bool k_KeepSceneObjects = false;
  46. #endif
  47. [OneTimeSetUp]
  48. public void OneTimeSetup()
  49. {
  50. if (EditorApplication.isPlaying)
  51. return;
  52. AssetDatabase.DeleteAsset(k_TempFolder);
  53. var folderGUID = AssetDatabase.CreateFolder(k_ParentFolder, k_TempFolderName);
  54. Assume.That(folderGUID, Is.Not.Empty);
  55. SessionState.SetBool(k_AutoSaveKey, PrefabStageAutoSavingUtil.GetPrefabStageAutoSave());
  56. PrefabStageAutoSavingUtil.SetPrefabStageAutoSave(false);
  57. StageUtility.GoToMainStage();
  58. m_PreviousScenePath = SceneManager.GetActiveScene().path;
  59. m_TempScenePath = Path.Combine(k_TempFolder, "NavMeshSurfacePrefabVariantTestsScene.unity");
  60. var tempScene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Single);
  61. EditorSceneManager.SaveScene(tempScene, m_TempScenePath);
  62. EditorSceneManager.OpenScene(m_TempScenePath);
  63. s_EnterPlayModeOptionsEnabled = EditorSettings.enterPlayModeOptionsEnabled;
  64. s_EnterPlayModeOptions = EditorSettings.enterPlayModeOptions;
  65. EditorSettings.enterPlayModeOptionsEnabled = true;
  66. EditorSettings.enterPlayModeOptions = EnterPlayModeOptions.DisableDomainReload | EnterPlayModeOptions.DisableSceneReload;
  67. }
  68. [OneTimeTearDown]
  69. public void OneTimeTearDown()
  70. {
  71. if (EditorApplication.isPlaying)
  72. return;
  73. PrefabStageAutoSavingUtil.SetPrefabStageAutoSave(SessionState.GetBool(k_AutoSaveKey, PrefabStageAutoSavingUtil.GetPrefabStageAutoSave()));
  74. StageUtility.GoToMainStage();
  75. EditorSceneManager.SaveScene(SceneManager.GetActiveScene());
  76. if (string.IsNullOrEmpty(m_PreviousScenePath))
  77. EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Single);
  78. EditorSettings.enterPlayModeOptionsEnabled = s_EnterPlayModeOptionsEnabled;
  79. EditorSettings.enterPlayModeOptions = s_EnterPlayModeOptions;
  80. #if !KEEP_ARTIFACTS_FOR_INSPECTION
  81. AssetDatabase.DeleteAsset(k_TempFolder);
  82. #endif
  83. }
  84. [UnitySetUp]
  85. public IEnumerator SetupVariantOfPrefabWithNavMesh()
  86. {
  87. if (EditorApplication.isPlaying)
  88. yield break;
  89. var plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
  90. plane.name = "NavMeshSurfacePrefab" + (++m_TestCounter);
  91. var surface = plane.AddComponent<NavMeshSurface>();
  92. surface.collectObjects = CollectObjects.Children;
  93. m_PrefabPath = Path.Combine(k_TempFolder, plane.name + ".prefab");
  94. m_PrefabVariantPath = Path.Combine(k_TempFolder, plane.name + "Variant.prefab");
  95. var planePrefab = PrefabUtility.SaveAsPrefabAsset(plane, m_PrefabPath);
  96. Object.DestroyImmediate(plane);
  97. AssetDatabase.OpenAsset(planePrefab);
  98. var theOriginalPrefabStage = PrefabStageUtility.GetCurrentPrefabStage();
  99. var theOriginalPrefabSurface = theOriginalPrefabStage.prefabContentsRoot.GetComponent<NavMeshSurface>();
  100. yield return TestUtility.BakeNavMeshAsync(theOriginalPrefabSurface, k_PrefabDefaultArea);
  101. PrefabSavingUtil.SavePrefab(theOriginalPrefabStage);
  102. StageUtility.GoToMainStage();
  103. var instanceForVariant = PrefabUtility.InstantiatePrefab(planePrefab) as GameObject;
  104. PrefabUtility.SaveAsPrefabAsset(instanceForVariant, m_PrefabVariantPath);
  105. instanceForVariant!.name += "_Saved";
  106. TestUtility.EliminateFromScene(ref instanceForVariant, k_KeepSceneObjects);
  107. NavMesh.RemoveAllNavMeshData();
  108. yield return null;
  109. }
  110. [UnityTearDown]
  111. public IEnumerator TearDown()
  112. {
  113. if (EditorApplication.isPlaying)
  114. yield return new ExitPlayMode();
  115. StageUtility.GoToMainStage();
  116. yield return null;
  117. }
  118. [UnityTest]
  119. public IEnumerator NavMeshSurfacePrefabVariant_WhenFreshAndRebaked_ParentAssetUnchanged(
  120. [Values(RunMode.EditMode, RunMode.PlayMode)]
  121. RunMode runMode)
  122. {
  123. var theOriginalPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(m_PrefabPath);
  124. AssetDatabase.OpenAsset(theOriginalPrefab);
  125. if (runMode == RunMode.PlayMode)
  126. yield return new EnterPlayMode();
  127. var theOriginalPrefabStage = PrefabStageUtility.GetCurrentPrefabStage();
  128. var theOriginalPrefabSurface = theOriginalPrefabStage.prefabContentsRoot.GetComponent<NavMeshSurface>();
  129. var theOriginalPrefabNavMeshData = theOriginalPrefabSurface.navMeshData;
  130. var theOriginalPrefabAssetPath = AssetDatabase.GetAssetPath(theOriginalPrefabSurface.navMeshData);
  131. Assert.IsTrue(theOriginalPrefabNavMeshData != null, "Original prefab must have some NavMeshData.");
  132. Assert.IsTrue(File.Exists(theOriginalPrefabAssetPath), "NavMeshData file must exist for the original prefab. ({0})", theOriginalPrefabAssetPath);
  133. var prefabVariant = AssetDatabase.LoadAssetAtPath<GameObject>(m_PrefabVariantPath);
  134. AssetDatabase.OpenAsset(prefabVariant);
  135. var prefabVariantStage = PrefabStageUtility.GetCurrentPrefabStage();
  136. var prefabVariantSurface = prefabVariantStage.prefabContentsRoot.GetComponent<NavMeshSurface>();
  137. var initialVariantNavMeshData = prefabVariantSurface.navMeshData;
  138. var initialVariantAssetPath = AssetDatabase.GetAssetPath(prefabVariantSurface.navMeshData);
  139. Assert.AreEqual(theOriginalPrefabNavMeshData, initialVariantNavMeshData, "Fresh variant must have the same NavMeshData as the original prefab.");
  140. Assert.IsTrue(initialVariantNavMeshData != null, "Prefab must have some NavMeshData.");
  141. Assert.IsTrue(File.Exists(initialVariantAssetPath), "NavMeshData file must exist. ({0})", initialVariantAssetPath);
  142. yield return TestUtility.BakeNavMeshAsync(prefabVariantSurface, k_GrayArea);
  143. Assert.IsTrue(initialVariantNavMeshData != null, "The initial NavMeshData (from original prefab) must still exist immediately after prefab variant re-bake.");
  144. Assert.IsTrue(File.Exists(initialVariantAssetPath), "The initial NavMeshData file (from original prefab) must exist after prefab variant re-bake. ({0})", initialVariantAssetPath);
  145. Assert.IsTrue(prefabVariantSurface.navMeshData != null, "NavMeshSurface must have NavMeshData after baking.");
  146. var unsavedRebakedNavMeshData = prefabVariantSurface.navMeshData;
  147. yield return TestUtility.BakeNavMeshAsync(prefabVariantSurface, k_BrownArea);
  148. Assert.IsTrue(unsavedRebakedNavMeshData == null, "An unsaved NavMeshData should not exist after a re-bake.");
  149. Assert.IsTrue(prefabVariantSurface.navMeshData != null, "NavMeshSurface must have NavMeshData after baking.");
  150. PrefabSavingUtil.SavePrefab(prefabVariantStage);
  151. var theNewVariantNavMeshData = prefabVariantSurface.navMeshData;
  152. var theNewVariantAssetPath = AssetDatabase.GetAssetPath(theNewVariantNavMeshData);
  153. Assert.IsTrue(File.Exists(theNewVariantAssetPath), "Variant's own NavMeshData exists in a file after saving. ({0})", theNewVariantAssetPath);
  154. Assert.IsTrue(File.Exists(theOriginalPrefabAssetPath), "NavMeshData file of the original prefab still exists after saving the variant. ({0})", theOriginalPrefabAssetPath);
  155. Assert.IsTrue(theOriginalPrefabNavMeshData != null, "Original prefab must still have NavMeshData.");
  156. StageUtility.GoToMainStage();
  157. yield return null;
  158. if (EditorApplication.isPlaying)
  159. yield return new ExitPlayMode();
  160. }
  161. [UnityTest]
  162. public IEnumerator NavMeshSurfacePrefabVariant_WhenCustomizedAndRebaked_OldAssetDiscardedAndParentAssetUnchanged(
  163. [Values(RunMode.EditMode, RunMode.PlayMode)]
  164. RunMode runMode)
  165. {
  166. var prefabVariant = AssetDatabase.LoadAssetAtPath<GameObject>(m_PrefabVariantPath);
  167. var theOriginalPrefabPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefabVariant);
  168. var theOriginalPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(theOriginalPrefabPath);
  169. AssetDatabase.OpenAsset(theOriginalPrefab);
  170. if (runMode == RunMode.PlayMode)
  171. yield return new EnterPlayMode();
  172. var theOriginalPrefabStage = PrefabStageUtility.GetCurrentPrefabStage();
  173. var theOriginalPrefabSurface = theOriginalPrefabStage.prefabContentsRoot.GetComponent<NavMeshSurface>();
  174. var theOriginalPrefabNavMeshData = theOriginalPrefabSurface.navMeshData;
  175. var theOriginalPrefabAssetPath = AssetDatabase.GetAssetPath(theOriginalPrefabSurface.navMeshData);
  176. Assert.IsTrue(theOriginalPrefabNavMeshData != null, "Original prefab must have some NavMeshData.");
  177. Assert.IsTrue(File.Exists(theOriginalPrefabAssetPath), "NavMeshData file must exist for the original prefab. ({0})", theOriginalPrefabAssetPath);
  178. AssetDatabase.OpenAsset(prefabVariant);
  179. var prefabVariantStage = PrefabStageUtility.GetCurrentPrefabStage();
  180. var prefabVariantSurface = prefabVariantStage.prefabContentsRoot.GetComponent<NavMeshSurface>();
  181. yield return TestUtility.BakeNavMeshAsync(prefabVariantSurface, k_GrayArea);
  182. PrefabSavingUtil.SavePrefab(prefabVariantStage);
  183. var modifiedVariantNavMeshData = prefabVariantSurface.navMeshData;
  184. var modifiedVariantAssetPath = AssetDatabase.GetAssetPath(prefabVariantSurface.navMeshData);
  185. Assert.IsTrue(modifiedVariantNavMeshData != null, "Prefab must have some NavMeshData.");
  186. Assert.IsTrue(File.Exists(modifiedVariantAssetPath), "NavMeshData file for modifier variant must exist. ({0})", modifiedVariantAssetPath);
  187. Assert.AreNotEqual(theOriginalPrefabNavMeshData, modifiedVariantNavMeshData, "Modified variant must have a NavMeshData different than that of the original prefab.");
  188. yield return TestUtility.BakeNavMeshAsync(prefabVariantSurface, k_OrangeArea);
  189. Assert.IsTrue(modifiedVariantNavMeshData != null, "The initial NavMeshData of a modified variant must still exist immediately after prefab variant re-bake.");
  190. Assert.IsTrue(File.Exists(modifiedVariantAssetPath), "The initial NavMeshData file of a modified variant must exist after prefab variant re-bake. ({0})", modifiedVariantAssetPath);
  191. Assert.IsTrue(prefabVariantSurface.navMeshData != null, "NavMeshSurface must have NavMeshData after baking.");
  192. var unsavedRebakedNavMeshData = prefabVariantSurface.navMeshData;
  193. yield return TestUtility.BakeNavMeshAsync(prefabVariantSurface, k_RedArea);
  194. Assert.IsTrue(unsavedRebakedNavMeshData == null, "An unsaved NavMeshData should not exist after a re-bake.");
  195. Assert.IsTrue(prefabVariantSurface.navMeshData != null, "NavMeshSurface must have NavMeshData after baking.");
  196. PrefabSavingUtil.SavePrefab(prefabVariantStage);
  197. var theNewVariantNavMeshData = prefabVariantSurface.navMeshData;
  198. var theNewVariantAssetPath = AssetDatabase.GetAssetPath(theNewVariantNavMeshData);
  199. if (EditorApplication.isPlaying)
  200. {
  201. Assert.IsTrue(modifiedVariantNavMeshData != null, "Playmode: Initial NavMeshData of the modified variant must still exist until the end of playmode.");
  202. 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);
  203. }
  204. else
  205. {
  206. Assert.IsTrue(modifiedVariantNavMeshData == null, "Editmode: Initial NavMeshData of the modified variant must no longer exist after saving the variant.");
  207. // This code is still reachable because modifiedVariantNavMeshData has been affected by BakeNavMeshAsync()
  208. 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);
  209. }
  210. Assert.IsTrue(File.Exists(theNewVariantAssetPath), "Variant's own NavMeshData exists in a file after saving. ({0})", theNewVariantAssetPath);
  211. Assert.IsTrue(File.Exists(theOriginalPrefabAssetPath), "NavMeshData file of the original prefab still exists after saving the variant. ({0})", theOriginalPrefabAssetPath);
  212. Assert.AreNotEqual(theOriginalPrefabNavMeshData, theNewVariantNavMeshData, "Re-baked modified variant must have a NavMeshData different than that of the original prefab.");
  213. StageUtility.GoToMainStage();
  214. yield return null;
  215. if (EditorApplication.isPlaying)
  216. yield return new ExitPlayMode();
  217. }
  218. }
  219. }