LoginSignup
11
7

More than 5 years have passed since last update.

UnityEditorで動的にメニューを生成する方法

Last updated at Posted at 2016-10-13

UnityEditorでは簡単に開発用のメニューを追加することができるんですが、私が調べた限りでは、動的にメニュー項目を生成することはできないようです。確かに、MenuItemプロパティとしてスクリプトに指定するものなので、実行時にどうこうという話ではありません。

が、ひと手間かければできることが分かりました。一言で言うと、

メニュー用スクリプトをメニューハンドラ内で動的生成してアセットとして追加する

です。一度メニューを実行するというひと手間が入ってしまいますが、目的によっては十分使える仕組みだと思います。

例えば、特定のフォルダ内にあるシーンをリストアップしてメニューから開くことができるようにするEditorスクリプトはこんな感じになります。一度メニューの"Assets/Create Scene List"を実行して、しばらく待つと、同じところにシーンリストが登録され、開くことができるようになります。

SceneListCreator.cs
using UnityEngine;
using UnityEditor;
using System.IO;

public class SceneListCreator
{
    [MenuItem("Assets/Create Scene List", false, 7651)]
    public static void CreateSceneList()
    {
        string[] sceneDirs = { "Assets/Test/Scenes" };
        string scriptDir = "Test/Editor";
        string scriptName = "SceneList.cs";

        string scriptFilePath = Application.dataPath + "/" + scriptDir + "/" + scriptName;
        string scriptAssetPath = "Assets/" + scriptDir + "/" + scriptName;

        using (StreamWriter sw = File.CreateText(scriptFilePath))
        {
            sw.WriteLine("using UnityEngine;");
            sw.WriteLine("using System.Collections;");
            sw.WriteLine("using UnityEditor;");
            sw.WriteLine("using UnityEditor.SceneManagement;");
            sw.WriteLine("");
            sw.WriteLine("public class SceneList");
            sw.WriteLine("{");

            string[] sceneGUIDs = AssetDatabase.FindAssets("t:Scene", sceneDirs);
            foreach (var sceneGUID in sceneGUIDs)
            {
                string scenePath = AssetDatabase.GUIDToAssetPath(sceneGUID);
                string[] splittedScenePath = scenePath.Split(new char[] { '/' });
                string sceneName = splittedScenePath[splittedScenePath.Length - 1].Replace(".unity", "");
                sw.WriteLine("    [MenuItem(\"Assets/Scene/" + sceneName + "\", false, 7650)]");
                sw.WriteLine("    public static void OpenScene" + sceneName + "()");
                sw.WriteLine("    {");
                sw.WriteLine("        if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())");
                sw.WriteLine("            EditorSceneManager.OpenScene(\"" + scenePath + "\");");
                sw.WriteLine("    }");
            }

            sw.WriteLine("}");
        }
        AssetDatabase.ImportAsset(scriptAssetPath);
    }
}

書き出すスクリプトファイル名(scriptName)やスクリプトディレクトリ(scriptDir)、AssetDatabase.FindAssetsに渡すアセット検索ディレクトリ(sceneDirs)はご自分の環境に合わせて変更してください(プロジェクト内全探索は大きなプロジェクトだとちょっと怖いので却下)。もちろんメニュー位置もご自由に。

Unity_SceneList.png

っていうか、なんでメニューに"Recent Scenes"がないんでしょうね? あったら絶対に便利なのに。ということで、不便なので作ってみたのでした。

なお、アイデアはこちらから頂きました。Grazie Marco!
Creating Dynamic MenuItems in Unity
http://www.marcosecchi.it/2015/12/03/creating-dynamic-menuitems-in-unity/?lang=en

11
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
7