メニューバーにシーンを切り替える項目を作ると人生が楽になる【Unity】

ある程度プロジェクトが複雑になってきた時、特定のシーンを開いてはまた別のシーンを開いて作業。。とシーンを右往左往するのは探すのも含め結構面倒ですよね。

この問題はメニューバーでシーンを切り替えれるように拡張することで緩和が出来ます。

######結論　↓の選択したシーンを開くメニューバーを今回は作る
![1frame 53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497331/c726d503-32d7-c110-3f35-76753585a2d6.png)


作り方
---------------------

メニューバーにシーンを開く処理を作るだけならこのコードを書くだけで移動できるようになります。

        [MenuItem("OpenScene/Assets/Scenes/Boot.unity")]
        private static void OpenBootScene()
        {
            // シーンの変更があった場合にどうするか聞く
            if (UnityEditor.SceneManagement.EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
            {
                UnityEditor.SceneManagement.EditorSceneManager.OpenScene("Assets/Scenes/Boot.unity");
            }
        }


しかし、これだとシーンを作る度にソースコードに追記していく必要が出てきたり
既にシーンが複数存在する場合全て書いていくのは少々面倒です。このコードを自動で生成させるようにします。

自動生成できるように
------------------------
まず、自動生成するテンプレートを作る

            #region 定数
            private static string ASSETS_PATH = Application.dataPath + "/";
    
            private static string SOURCE_TEMPLATE =
    @"
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using UnityEngine;
    using UnityEditor;
    
    namespace Common
    {
        public class #SCRIPTNAME#
        { 
            #WRITE#
        }
    }";
    
    
            private static string OPENSCENE_TEMPLATE =
    @"
            [MenuItem(#TOOL_PATH#)]
            private static void Open#NAME#Scene()
            {
                // シーンの変更があった場合にどうするか聞く
                if (UnityEditor.SceneManagement.EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
                {
                    UnityEditor.SceneManagement.EditorSceneManager.OpenScene(#PATH#);
                }
            }
    ";


        #endregion


後は自動生成する処理とそれを呼び出す関数を用意

        [MenuItem("MyTool/CreateOpenScene")]
        private static void ScenePathCreater()
        {
            List<string> scenePathList = new List<string>();

            StringBuilder margeText = new StringBuilder();
            for (int i = 0; i < EditorBuildSettings.scenes.Length; i++)
            {
                StringBuilder text = new StringBuilder(OPENSCENE_TEMPLATE);

                text.Replace("#TOOL_PATH#", EncloseDoubleQuotation("OpenScene/"+EditorBuildSettings.scenes[i].path)).
                     Replace("#NAME#", Path.GetFileNameWithoutExtension(EditorBuildSettings.scenes[i].path)).
                     Replace("#PATH#", EncloseDoubleQuotation(EditorBuildSettings.scenes[i].path));

                margeText.Append(text);
                margeText.AppendLine();
            }

            // ファイル生成
            CreateSourceFile(margeText, "OpenScene");
        }
        
        /// <summary>
        /// ファイル生成
        /// </summary>
        /// <param name="vs"></param>
        /// <param name="fileName"></param>
        private static void CreateSourceFile(StringBuilder writeText, string fileName)
        {
            // インポート開始
            AssetDatabase.StartAssetEditing();

            StreamWriter cs = new StreamWriter(ASSETS_PATH + fileName + ".cs", false, Encoding.UTF8);

            // 書き出すコードを組み立てる
            StringBuilder stringBuilder = new StringBuilder(SOURCE_TEMPLATE);
            stringBuilder.Replace("#SCRIPTNAME#", fileName);
            stringBuilder.Replace("#WRITE#", writeText.ToString());

            // ファイルにコードを書き込む
            cs.Write(stringBuilder);

            // ファイルを閉じる
            cs.Close();

            // インポート終了
            AssetDatabase.StopAssetEditing();

            // アセットインポートする
            AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
        }

        /// <summary>
        /// ""で囲む
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        private static string EncloseDoubleQuotation(string text)
        {
            StringBuilder export = new StringBuilder();
            export.Append("\"").Append(text).Append("\"");
            return export.ToString();
        }



###開始

![gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497331/18ac38e9-c36a-55d5-a3c3-6584a16f4026.gif)

生成したソースの中身↓

    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using UnityEngine;
    using UnityEditor;
    
    namespace Common
    {
        public class OpenScene
        { 
            
            [MenuItem("OpenScene/Assets/Scenes/Boot.unity")]
            private static void OpenBootScene()
            {
                // シーンの変更があった場合にどうするか聞く
                if (UnityEditor.SceneManagement.EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
                {
                    UnityEditor.SceneManagement.EditorSceneManager.OpenScene("Assets/Scenes/Boot.unity");
                }
            }
    

            [MenuItem("OpenScene/Assets/Scenes/Main.unity")]
            private static void OpenMainScene()
            {
                // シーンの変更があった場合にどうするか聞く
                if (UnityEditor.SceneManagement.EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
                {
                    UnityEditor.SceneManagement.EditorSceneManager.OpenScene("Assets/Scenes/Main.unity");
                }
            }
    

            [MenuItem("OpenScene/Assets/Scenes/Title.unity")]
            private static void OpenTitleScene()
            {
                // シーンの変更があった場合にどうするか聞く
                if (UnityEditor.SceneManagement.EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
                {
                    UnityEditor.SceneManagement.EditorSceneManager.OpenScene("Assets/Scenes/Title.unity");
                }
            }
    

        }
    }

おわり
------------
メニューバーからシーンへ移動できるようになりました。
シーンを生成した時をフックして生成する命令を呼び出しても良いかもしれませんね

今回は前の記事で書いたコードを生成する機能の応用も兼ねています、
作り方次第で色々なショートカットに使えそうなので、ぜひ試してみてはどうでしょうか。