質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

1291閲覧

シーンのLoad/Unload/Removeをショートカットで呼び出したい

Gorisan

総合スコア1

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2021/06/15 18:37

前提・実現したいこと

エディタ上で複数のシーンを開いているとき、
ヒエラルキービューのシーン名を選択して右クリックするといくつかのメニューが表示されますよね。

その中にLoadScene/UnloadScene/RemoveSceneがあると思うのですが、
これらを右クリックを経由せず、ショートカットキーの操作で実行したいです。

発生している問題

ヒエラルキー上で選択されているシーンの取得方法がわからない

試したこと

・まずショートカットマネージャーを調べたが、これらに該当する機能は見当たらなかった。

・editorでショートカットを自作しようといろいろ調べ、ショートカットの作成自体はできるようになった。
が、ゲームオブジェクトを選択したときの操作しかできない。

・というのも、調べた方法では「Selection」で対象を取得していたが、
「Selection」では「シーン上のオブジェクト」しか取得できず、「シーンそのもの」を取得する方法がわからないため。

・Unityのスクリプトリファレンスで関係ありそうな場所
(Editor、Selection、MenuCommand、EditorSceneManagerなど)を調べたがわからなかった。

「ヒエラルキーで選択しているシーン」を取得できれば切り替え自体は容易だと思うのですが、
肝心の「ヒエラルキーで選択しているシーン」の取得方法がわかりません。

もしご存知の方おられたら教えていただけませんか。
よろしくお願いします。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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}

メニュー項目にショートカットを割り当てれば...

図1

キーボード操作でアンロード・リムーブ・ロードを行えました。

図2

ちなみに、SceneHierarchyWindowSceneHierarchyにはご質問者さんのおっしゃる「ヒエラルキーで選択しているシーン」を取得するメソッドもあるようです。
たとえば、今回例示したUnloadSelectedScenesとかRemoveSelectedScenesの場合は選択範囲に未保存のシーンが含まれていると保存するかどうか確認してきますが、そうではなくて「未保存の変更があろうが問答無用でアンロードする」といった動作をさせたい場合は、そちらを使って独自のメソッドを作ることができるかもしれません。

投稿2021/06/16 11:01

Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Gorisan

2021/06/16 17:55

ご教授いただいた方法で無事、ショートカット登録できました。 わざわざリフレクションで取ってこないといけないようなものだったとは。 私が想像していたよりもはるかに複雑だったようですね。 これで右クリック~メニュー選択の手間を省けます。 迅速ですばらしい回答、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問