No Description
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.

NavMeshUpdaterUtility.cs 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #if UNITY_2022_2_OR_NEWER
  2. using System;
  3. using System.IO;
  4. using UnityEditor;
  5. using UnityEditor.SceneManagement;
  6. using UnityEngine;
  7. using UnityEngine.AI;
  8. using UnityEngine.SceneManagement;
  9. namespace Unity.AI.Navigation.Updater
  10. {
  11. internal static class NavMeshUpdaterUtility
  12. {
  13. const string k_NavMeshSettingsPropertyPath = "NavMeshSettings";
  14. const string k_NavMeshDataPropertyPath = "m_NavMeshData";
  15. const string k_EmptyFileIdSerialization = "{fileID: 0}";
  16. const string k_DefaultNavMeshSurfaceName = "Navigation";
  17. const int k_WalkableAreaId = 0;
  18. public static bool ConvertScene(string path)
  19. {
  20. Scene previousActiveScene = SceneManager.GetActiveScene();
  21. OpenAndSetActiveScene(path, out Scene convertedScene, out bool alreadyOpened);
  22. // Retrieve the legacy NavMesh data from the active scene
  23. var settingObject = new SerializedObject(UnityEditor.AI.NavMeshBuilder.navMeshSettingsObject);
  24. var navMeshDataProperty = settingObject.FindProperty(k_NavMeshDataPropertyPath);
  25. var navMeshData = navMeshDataProperty.objectReferenceValue as NavMeshData;
  26. if (navMeshData == null)
  27. {
  28. Debug.LogWarning("The NavMesh asset referenced in the scene is missing or corrupted.");
  29. return false;
  30. }
  31. // Convert static Navigation Flags with a NavMeshModifier
  32. GameObject[] rootObjects = convertedScene.GetRootGameObjects();
  33. var sceneObjects = SceneModeUtility.GetObjects(rootObjects, true);
  34. foreach (GameObject go in sceneObjects)
  35. ConvertStaticValues(go);
  36. // Create a global NavMeshSurface and copy legacy NavMesh settings
  37. var surfaceObject = new GameObject(k_DefaultNavMeshSurfaceName, typeof(NavMeshSurface));
  38. var navMeshSurface = surfaceObject.GetComponent<NavMeshSurface>();
  39. navMeshSurface.navMeshData = navMeshData;
  40. NavMeshBuildSettings settings = navMeshData.buildSettings;
  41. navMeshSurface.collectObjects = CollectObjects.MarkedWithModifier;
  42. navMeshSurface.useGeometry = NavMeshCollectGeometry.RenderMeshes;
  43. navMeshSurface.overrideVoxelSize = settings.overrideVoxelSize;
  44. navMeshSurface.voxelSize = settings.voxelSize;
  45. navMeshSurface.overrideTileSize = settings.overrideTileSize;
  46. navMeshSurface.tileSize = settings.tileSize;
  47. navMeshSurface.minRegionArea = settings.minRegionArea;
  48. navMeshSurface.buildHeightMesh = settings.buildHeightMesh;
  49. // Remove NavMeshData reference from the scene
  50. navMeshDataProperty.objectReferenceValue = null;
  51. settingObject.ApplyModifiedProperties();
  52. // Rename NavMesh asset
  53. var assetPath = AssetDatabase.GetAssetPath(navMeshData);
  54. AssetDatabase.RenameAsset(assetPath, "NavMesh-" + navMeshSurface.name + ".asset");
  55. AssetDatabase.Refresh();
  56. EditorSceneManager.SaveScene(convertedScene);
  57. navMeshSurface.AddData();
  58. if (!alreadyOpened)
  59. EditorSceneManager.CloseScene(convertedScene, true);
  60. SceneManager.SetActiveScene(previousActiveScene);
  61. return true;
  62. }
  63. private static void OpenAndSetActiveScene(string path, out Scene scene, out bool alreadyOpened)
  64. {
  65. for (int i = 0; i < SceneManager.sceneCount; i++)
  66. {
  67. scene = SceneManager.GetSceneAt(i);
  68. if (!scene.isLoaded)
  69. continue;
  70. if (path == scene.path)
  71. {
  72. if (SceneManager.GetActiveScene() != scene)
  73. SceneManager.SetActiveScene(scene);
  74. alreadyOpened = true;
  75. return;
  76. }
  77. }
  78. scene = EditorSceneManager.OpenScene(path, OpenSceneMode.Additive);
  79. SceneManager.SetActiveScene(scene);
  80. alreadyOpened = false;
  81. }
  82. private static void ConvertStaticValues(GameObject go)
  83. {
  84. // Disable CS0618 warning about StaticEditorFlags.NavigationStatic and StaticEditorFlags.OffMeshLinkGeneration being deprecated
  85. #pragma warning disable 618
  86. var staticFlags = GameObjectUtility.GetStaticEditorFlags(go);
  87. if ((staticFlags & StaticEditorFlags.NavigationStatic) != 0)
  88. {
  89. NavMeshModifier modifier = go.AddComponent<NavMeshModifier>();
  90. modifier.area = GameObjectUtility.GetNavMeshArea(go);
  91. if (modifier.area != k_WalkableAreaId)
  92. modifier.overrideArea = true;
  93. if ((staticFlags & StaticEditorFlags.OffMeshLinkGeneration) != 0)
  94. {
  95. modifier.overrideGenerateLinks = true;
  96. modifier.generateLinks = true;
  97. }
  98. staticFlags &= ~StaticEditorFlags.NavigationStatic;
  99. GameObjectUtility.SetStaticEditorFlags(go, staticFlags);
  100. }
  101. #pragma warning restore 618
  102. }
  103. internal static bool IsSceneReferencingLegacyNavMesh(string path)
  104. {
  105. if (string.IsNullOrEmpty(path))
  106. throw new ArgumentNullException(nameof(path));
  107. if (path.StartsWith("Packages"))
  108. return false;
  109. if (!path.EndsWith(".unity", StringComparison.OrdinalIgnoreCase))
  110. return false;
  111. using (StreamReader file = File.OpenText(path))
  112. {
  113. string line;
  114. bool skipUntilSettings = true;
  115. while ((line = file.ReadLine()) != null)
  116. {
  117. if (skipUntilSettings)
  118. {
  119. if (line.Contains($"{k_NavMeshSettingsPropertyPath}:"))
  120. skipUntilSettings = false;
  121. }
  122. else
  123. {
  124. if (line.Contains($"{k_NavMeshDataPropertyPath}:"))
  125. {
  126. return !line.Contains(k_EmptyFileIdSerialization);
  127. }
  128. }
  129. }
  130. }
  131. return false;
  132. }
  133. }
  134. }
  135. #endif