前提・実現したいこと
エディタ上で複数のシーンを開いているとき、
ヒエラルキービューのシーン名を選択して右クリックするといくつかのメニューが表示されますよね。
その中にLoadScene/UnloadScene/RemoveSceneがあると思うのですが、
これらを右クリックを経由せず、ショートカットキーの操作で実行したいです。
発生している問題
ヒエラルキー上で選択されているシーンの取得方法がわからない
試したこと
・まずショートカットマネージャーを調べたが、これらに該当する機能は見当たらなかった。
・editorでショートカットを自作しようといろいろ調べ、ショートカットの作成自体はできるようになった。
が、ゲームオブジェクトを選択したときの操作しかできない。
・というのも、調べた方法では「Selection」で対象を取得していたが、
「Selection」では「シーン上のオブジェクト」しか取得できず、「シーンそのもの」を取得する方法がわからないため。
・Unityのスクリプトリファレンスで関係ありそうな場所
(Editor、Selection、MenuCommand、EditorSceneManagerなど)を調べたがわからなかった。
「ヒエラルキーで選択しているシーン」を取得できれば切り替え自体は容易だと思うのですが、
肝心の「ヒエラルキーで選択しているシーン」の取得方法がわかりません。
もしご存知の方おられたら教えていただけませんか。
よろしくお願いします。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
どうやらSceneHierarchyWindowがヒエラルキーウィンドウで、その中で使われているSceneHierarchyというのがヒエラルキーを表しているようですね。いろいろな操作はSceneHierarchy
が担当しているようです。
リフレクション祭りで見苦しくてすみませんが、下記のようなスクリプトを用意して...
lang
1using System; 2using System.Linq.Expressions; 3using System.Reflection; 4using UnityEditor; 5using UnityEngine; 6 7public static class SceneLoader 8{ 9 [MenuItem("Utility/Scene Management/Load Selected Scenes")] 10 public static void LoadScenes() 11 { 12 var sceneHierarchy = GetHierarchyFromLastInteractedWindow(); 13 if (sceneHierarchy != null) 14 { 15 LoadSelectedScenes(sceneHierarchy); 16 } 17 } 18 19 [MenuItem("Utility/Scene Management/Unload Selected Scenes")] 20 public static void UnloadScenes() 21 { 22 var sceneHierarchy = GetHierarchyFromLastInteractedWindow(); 23 if (sceneHierarchy != null) 24 { 25 UnloadSelectedScenes(sceneHierarchy); 26 } 27 } 28 29 [MenuItem("Utility/Scene Management/Remove Selected Scenes")] 30 public static void RemoveScenes() 31 { 32 var sceneHierarchy = GetHierarchyFromLastInteractedWindow(); 33 if (sceneHierarchy != null) 34 { 35 RemoveSelectedScenes(sceneHierarchy); 36 } 37 } 38 39 private static object GetHierarchyFromLastInteractedWindow() 40 { 41 // 最後に操作したヒエラルキーウィンドウを取得し... 42 var hierarchyWindow = GetLastInteractedHierarchyWindow(); 43 44 // SceneHierarchyを取得して返す 45 if (hierarchyWindow != null) 46 { 47 return GetSceneHierarchy(hierarchyWindow); 48 } 49 50 // ヒエラルキーウィンドウを一つも開いていない、などの場合は 51 // ウィンドウを取得できないのでnullを返す 52 Debug.LogError("Hierarchy window not found."); 53 return null; 54 } 55 56 private const BindingFlags SceneHierarchyBindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic; 57 58 private static Type sceneHierarchyWindowType; 59 private static Type sceneHierarchyType; 60 private static Func<SearchableEditorWindow> getLastInteractedHierarchyWindow; 61 private static Func<SearchableEditorWindow, object> getSceneHierarchy; 62 private static Action<object> loadSelectedScenes; 63 private static Action<object> unloadSelectedScenes; 64 private static Action<object> removeSelectedScenes; 65 66 private static Type SceneHierarchyWindowType => sceneHierarchyWindowType ??= 67 typeof(SearchableEditorWindow).Assembly.GetType("UnityEditor.SceneHierarchyWindow"); 68 private static Type SceneHierarchyType => sceneHierarchyType ??= 69 SceneHierarchyWindowType.Assembly.GetType("UnityEditor.SceneHierarchy"); 70 private static Func<SearchableEditorWindow> GetLastInteractedHierarchyWindow => getLastInteractedHierarchyWindow ??= 71 (Func<SearchableEditorWindow>)Delegate.CreateDelegate(typeof(Func<SearchableEditorWindow>), 72 SceneHierarchyWindowType.GetProperty("lastInteractedHierarchyWindow").GetMethod); 73 private static Func<SearchableEditorWindow, object> GetSceneHierarchy 74 { 75 get 76 { 77 if (getSceneHierarchy == null) 78 { 79 var target = Expression.Parameter(typeof(SearchableEditorWindow)); 80 getSceneHierarchy = Expression.Lambda<Func<SearchableEditorWindow, object>>( 81 Expression.Call(Expression.TypeAs(target, SceneHierarchyWindowType), 82 SceneHierarchyWindowType.GetProperty("sceneHierarchy").GetMethod), 83 target).Compile(); 84 } 85 return getSceneHierarchy; 86 } 87 } 88 private static Action<object> LoadSelectedScenes 89 { 90 get 91 { 92 if (loadSelectedScenes == null) 93 { 94 var target = Expression.Parameter(typeof(object)); 95 loadSelectedScenes = Expression.Lambda<Action<object>>( 96 Expression.Call(Expression.TypeAs(target, SceneHierarchyType), 97 SceneHierarchyType.GetMethod("LoadSelectedScenes", SceneHierarchyBindingFlags), 98 Expression.Constant(null)), 99 target).Compile(); 100 } 101 return loadSelectedScenes; 102 } 103 } 104 private static Action<object> UnloadSelectedScenes 105 { 106 get 107 { 108 if (unloadSelectedScenes == null) 109 { 110 var target = Expression.Parameter(typeof(object)); 111 unloadSelectedScenes = Expression.Lambda<Action<object>>( 112 Expression.Call(Expression.TypeAs(target, SceneHierarchyType), 113 SceneHierarchyType.GetMethod("UnloadSelectedScenes", SceneHierarchyBindingFlags), 114 Expression.Constant(null)), 115 target).Compile(); 116 } 117 return unloadSelectedScenes; 118 } 119 } 120 private static Action<object> RemoveSelectedScenes 121 { 122 get 123 { 124 if (removeSelectedScenes == null) 125 { 126 var target = Expression.Parameter(typeof(object)); 127 removeSelectedScenes = Expression.Lambda<Action<object>>( 128 Expression.Call(Expression.TypeAs(target, SceneHierarchyType), 129 SceneHierarchyType.GetMethod("RemoveSelectedScenes", SceneHierarchyBindingFlags), 130 Expression.Constant(null)), 131 target).Compile(); 132 } 133 return removeSelectedScenes; 134 } 135 } 136}
メニュー項目にショートカットを割り当てれば...
キーボード操作でアンロード・リムーブ・ロードを行えました。
ちなみに、SceneHierarchyWindow
やSceneHierarchy
にはご質問者さんのおっしゃる「ヒエラルキーで選択しているシーン」を取得するメソッドもあるようです。
たとえば、今回例示したUnloadSelectedScenes
とかRemoveSelectedScenes
の場合は選択範囲に未保存のシーンが含まれていると保存するかどうか確認してきますが、そうではなくて「未保存の変更があろうが問答無用でアンロードする」といった動作をさせたい場合は、そちらを使って独自のメソッドを作ることができるかもしれません。
投稿2021/06/16 11:01
総合スコア10811
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/06/16 17:55