我在2D游戏中使用A *寻路算法(据我了解,Unity Nav Meshes在2D中不起作用)。我希望能够为我的所有场景预先计算出导航网格,并将其保存在资源文件中,以便在播放器进入新场景时可以加载。无需记住要为每个场景单击“计算”-并记得在对导航网格进行更改后要重新计算所有场景-我希望能够以编程方式让Unity编辑器遍历每个场景并计算网格。
是否有一种方法可以在Unity编辑器中创建一个命令,该命令将迭代打开编辑器中的每个场景并在场景中的MonoBehaviour
上运行一个方法?另外,还有另一种方法可以完成我想做的事情吗?
答案 0 :(得分:4)
是的,可以的!
在编辑模式下,您不能使用SceneManager
,而必须使用EditorSceneManager
。
首先,您需要迭代的场景。
例如检查器中的public static
字段和SceneAsset
的列表,您可以在其中简单地引用场景
public static List<SceneAsset> Scenes = new List<SceneAsset>();
,或者您可以通过脚本获取它们,例如仅使用通过EditorBuildSettings.scenes
List<EditorBuildSettingsScene> Scenes = EditorBuildSettings.scenes;
对于两者,您都可以获取场景路径列表,例如使用LinQ Select
(基本上是foreach
循环的一种快捷方式)和AssetDatabase.GetAssetPath
List<string> scenePaths = Scenes.Select(scene => AssetDatabase.GetAssetPath(scene)).ToList();
对于EditorBuildSettings.scenes
中的EditorBuildSettingsScene,您也可以简单地使用
List<string> scenePaths = Scenes.Select(scene => scene.path).ToList();
现在,您可以遍历它们,并使用EditorSceneManager.OpenScene
,EditorSceneManager.SaveScene
和EditorSceneManager.CloseScene
(如果需要,AssetDatabase.SaveAssets)来完成您的工作
foreach(string scenePath in scenePaths)
{
// Open a scene e.g. in single mode
var currentScene = EditorSceneManager.OpenScene(scenePath);
/* Do your calculation for currentScene */
// Don't know if it makes changes to your scenes .. if not you can probably skip this
EditorSceneManager.SaveScene(currentScene);
// Finally Close and remove the scene
EditorSceneManager.CloseScene(currentScene, true);
}
// you might be doing changes to an asset you want to save when done
AssetDatabase.SaveAssets();
开始之前,您可能应该要求使用EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo
if(EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
// Saved => the foreach loop here
}
else
{
// aborted => do nothing
}
要最终启动该方法,最简单的方法是添加一个[MenuItem]
public static class Calculation
{
[MenuItem("YourMenu/RunCalculation")]
public static void RunCalculation()
{
// all the before mentioned snippets here
// depending how exactly you want to do it
}
}
这将在Unity Editor的顶部菜单栏中添加一个新菜单YourMenu
,其中有一个条目RunCalculation
。
注意:
由于这使用了仅存在于EditorSceneManager
名称空间中的许多类型(UnityEditor
等),因此您应该将整个脚本放在Editor
文件夹中(因此在最终版本中将其忽略) )或使用
#if UNITY_EDITOR
// ... code here
#endif
因此在构建中,代码也将被忽略。
请注意,到目前为止,我假设您也是在editmode下进行计算的。问题是,如果此计算依赖于任何Start
或Awake
方法上的某个位置,则必须在运行计算之前从该编辑器脚本手动调用它。