エディタ拡張でプレハブを配置するツールを作るのエディタウィンドウの値をオーバーレイで操作できるようにしてみました。
SerializedObjectにオーバーレイのVisualElementをバインドすることで、エディタウィンドウとオーバーレイの両方で同じ変数値を見たり変更できるようにします。
オーバーレイを定義
オーバーレイを作成します。CreatePanelContentメソッドでオーバーレイの内容を定義します。
- using UnityEditor;
- using UnityEditor.Overlays;
- using UnityEngine.UIElements;
- using UnityEditor.UIElements;
-
- [Overlay(displayName = "Prefab Placer", defaultDisplay = true)]
- public class PrefabPlacerOverlay : Overlay
- {
- PrefabPlacer placer;
-
- public PrefabPlacerOverlay(PrefabPlacer placer)
- {
- this.placer = placer;
- }
- public override VisualElement CreatePanelContent()
- {
- var root = new VisualElement() { name = "Prefab Placer" };
-
- // トグルを作成
- var toggle = new Toggle("Place Prefab");
-
- // バインディングパスを設定
- toggle.bindingPath = "placingPrefab";
-
- // SerializedObjectを作成
- var so = new SerializedObject(placer);
-
- // バインディングを作成
- root.Bind(so);
-
- root.Add(toggle);
-
- return root;
- }
- }
Overlay属性でeditorWindowTypeを指定しないことで永続化されないようにしています。
- [Overlay(displayName = "Prefab Placer", defaultDisplay = true)]
- public class PrefabPlacerOverlay : Overlay
CreatePanelContentメソッドでは、VisualElementインスタンスを返します。トグルが一つ表示されるようにしています。
- public override VisualElement CreatePanelContent()
- {
- var root = new VisualElement() { name = "Prefab Placer" };
-
- // トグルを作成
- var toggle = new Toggle("Place Prefab");
-
- // ...
-
- root.Add(toggle);
-
- return root;
- }
コンストラクタからエディタウィンドウが渡されるので、SerializedObjectを作りBindメソッドに渡します。
- public PrefabPlacerOverlay(PrefabPlacer placer)
- {
- this.placer = placer;
- }
バインドするフィールドの名前をBindableElement.bindingPathに設定します。
- // バインディングパスを設定
- toggle.bindingPath = "placingPrefab";
-
- // SerializedObjectを作成
- var so = new SerializedObject(placer);
-
- // バインディングを作成
- root.Bind(so);
EditorWindow
エディタウィンドウでは、バインドするフィールドにSerializeField属性をつけて、シリアライズします。
- [SerializeField] bool placingPrefab = false;
- bool PlacingPrefab { get => placingPrefab; set => placingPrefab = value; }
OnEnableメソッドでオーバーレイをインスタンス化し、SceneView.AddOverlayToActiveViewメソッドに渡しています。シーンビューにオーバーライドを追加します。
- PrefabPlacerOverlay overlay;
-
- private void OnEnable()
- {
- dataCollection = PrefabPlacerSettings.instance.Collection;
- SceneView.duringSceneGui += OnSceneGUI;
-
- overlay = new PrefabPlacerOverlay(this);
- SceneView.AddOverlayToActiveView(overlay);
-
- }
OnDisableメソッドでは、SceneView.RemoveOverlayFromActiveViewメソッドを呼んで、オーバーレイをシーンビューから取り除きます。
- void OnDisable()
- {
- // スクリプタブルシングルトンにデータを保存
- PrefabPlacerSettings.instance.SavePrefabCollection(dataCollection);
-
- SceneView.duringSceneGui -= OnSceneGUI;
-
- PlacingPrefab = false;
- SceneView.RemoveOverlayFromActiveView(overlay);
- }
エディタウィンドウとオーバーレイの両方から操作できるようになりました。

- // ボタンを押すとモードを変更
- if (GUILayout.Button(ButtonText))
- {
- TogglePlacingMode();
- }
-
- }
-
- EditorGUILayout.EndVertical();
- }
-
- public void TogglePlacingMode()
- {
- PlacingPrefab = !PlacingPrefab;
- }
-
- //...
- string ButtonText => PlacingPrefab ? "Stop Placing" : "Place Prefab";
参考:https://docs.unity3d.com/ja/2023.2/ScriptReference/Overlays.Overlay.html
https://docs.unity3d.com/ja/2022.3/Manual/overlays-custom.html
https://docs.unity3d.com/ja/2019.4/Manual/UIE-Binding.html
https://docs.unity3d.com/ja/2023.2/Manual/UIE-Binding.html