編輯視窗
為何選擇編輯視窗?
你可能已經看到,你可以在自定義檢查器中執行很多操作(如果你不知道自定義檢查器是什麼,請檢視此處的示例: http) : //stackoverflow.com/documentation/unity3d/2506/extending - 編輯)) 。但有時你可能希望實現配置面板或自定義資產調色盤。在這些情況下,你將使用 EditorWindow 。Unity UI 本身由 Editor Windows 組成; 你可以開啟它們(通常通過頂部欄),選項卡等。
建立一個基本的 EditorWindow
簡單的例子
建立自定義編輯器視窗非常簡單。你需要做的就是擴充套件 EditorWindow 類並使用 Init()
和 OnGUI()方法。這是一個簡單的例子:
using UnityEngine;
using UnityEditor;
public class CustomWindow : EditorWindow
{
// Add menu named "Custom Window" to the Window menu
[MenuItem("Window/Custom Window")]
static void Init()
{
// Get existing open window or if none, make a new one:
CustomWindow window = (CustomWindow) EditorWindow.GetWindow(typeof(CustomWindow));
window.Show();
}
void OnGUI()
{
GUILayout.Label("This is a custom Editor Window", EditorStyles.boldLabel);
}
}
三個重點是:
- 不要忘記擴充套件 EditorWindow
- 使用示例中提供的
Init()
。 EditorWindow.GetWindow 正在檢查是否已建立 CustomWindow。如果沒有,它將建立一個新例項。使用此選項可確保你不會同時擁有多個視窗例項 - 像往常一樣使用
OnGUI()
在視窗中顯示資訊
最終結果如下:
http://i.imgur.com/9O0TpTW.png
走得更遠
當然,你可能希望使用此 EditorWindow 管理或修改某些資產。下面是使用 Selection 類(獲取活動 Selection)並通過 SerializedObject 和 SerializedProperty 修改所選資產屬性的示例。
using System.Linq;
using UnityEngine;
using UnityEditor;
public class CustomWindow : EditorWindow
{
private AnimationClip _animationClip;
private SerializedObject _serializedClip;
private SerializedProperty _events;
private string _text = "Hello World";
// Add menu named "Custom Window" to the Window menu
[MenuItem("Window/Custom Window")]
static void Init()
{
// Get existing open window or if none, make a new one:
CustomWindow window = (CustomWindow) EditorWindow.GetWindow(typeof(CustomWindow));
window.Show();
}
void OnGUI()
{
GUILayout.Label("This is a custom Editor Window", EditorStyles.boldLabel);
// You can use EditorGUI, EditorGUILayout and GUILayout classes to display anything you want
// A TextField example
_text = EditorGUILayout.TextField("Text Field", _text);
// Note that you can modify an asset or a gameobject using an EditorWindow. Here is a quick example with an AnimationClip asset
// The _animationClip, _serializedClip and _events are set in OnSelectionChange()
if (_animationClip == null || _serializedClip == null || _events == null) return;
// We can modify our serializedClip like we would do in a Custom Inspector. For example we can grab its events and display their information
GUILayout.Label(_animationClip.name, EditorStyles.boldLabel);
for (var i = 0; i < _events.arraySize; i++)
{
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField(
"Event : " + _events.GetArrayElementAtIndex(i).FindPropertyRelative("functionName").stringValue,
EditorStyles.boldLabel);
EditorGUILayout.PropertyField(_events.GetArrayElementAtIndex(i).FindPropertyRelative("time"), true,
GUILayout.ExpandWidth(true));
EditorGUILayout.PropertyField(_events.GetArrayElementAtIndex(i).FindPropertyRelative("functionName"),
true, GUILayout.ExpandWidth(true));
EditorGUILayout.PropertyField(_events.GetArrayElementAtIndex(i).FindPropertyRelative("floatParameter"),
true, GUILayout.ExpandWidth(true));
EditorGUILayout.PropertyField(_events.GetArrayElementAtIndex(i).FindPropertyRelative("intParameter"),
true, GUILayout.ExpandWidth(true));
EditorGUILayout.PropertyField(
_events.GetArrayElementAtIndex(i).FindPropertyRelative("objectReferenceParameter"), true,
GUILayout.ExpandWidth(true));
EditorGUILayout.Separator();
EditorGUILayout.EndVertical();
}
// Of course we need to Apply the modified properties. We don't our changes won't be saved
_serializedClip.ApplyModifiedProperties();
}
/// This Message is triggered when the user selection in the editor changes. That's when we should tell our Window to Repaint() if the user selected another AnimationClip
private void OnSelectionChange()
{
_animationClip =
Selection.GetFiltered(typeof(AnimationClip), SelectionMode.Assets).FirstOrDefault() as AnimationClip;
if (_animationClip == null) return;
_serializedClip = new SerializedObject(_animationClip);
_events = _serializedClip.FindProperty("m_Events");
Repaint();
}
}
結果如下:
高階主題
你可以在編輯器中執行一些非常高階的操作,而 EditorWindow 類非常適合顯示大量資訊。Unity 資源商店中的大多數高階資產(例如 NodeCanvas 或 PlayMaker)使用 EditorWindow 顯示自定義檢視。
在 SceneView 中繪圖
與 EditorWindow 有關的一個有趣的事情是直接在 SceneView 中顯示資訊。通過這種方式,你可以建立完全自定義的地圖/世界編輯器,例如,使用自定義 EditorWindow 作為資產調色盤並在 SceneView 中單擊單擊以例項化新物件。這是一個例子:
using UnityEngine;
using System;
using UnityEditor;
public class CustomWindow : EditorWindow {
private enum Mode {
View = 0,
Paint = 1,
Erase = 2
}
private Mode CurrentMode = Mode.View;
[MenuItem ("Window/Custom Window")]
static void Init () {
// Get existing open window or if none, make a new one:
CustomWindow window = (CustomWindow)EditorWindow.GetWindow (typeof (CustomWindow));
window.Show();
}
void OnGUI () {
GUILayout.Label ("This is a custom Editor Window", EditorStyles.boldLabel);
}
void OnEnable() {
SceneView.onSceneGUIDelegate = SceneViewGUI;
if (SceneView.lastActiveSceneView) SceneView.lastActiveSceneView.Repaint();
}
void SceneViewGUI(SceneView sceneView) {
Handles.BeginGUI();
// We define the toolbars' rects here
var ToolBarRect = new Rect((SceneView.lastActiveSceneView.camera.pixelRect.width / 6), 10, (SceneView.lastActiveSceneView.camera.pixelRect.width * 4 / 6) , SceneView.lastActiveSceneView.camera.pixelRect.height / 5);
GUILayout.BeginArea(ToolBarRect);
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
CurrentMode = (Mode) GUILayout.Toolbar(
(int) CurrentMode,
Enum.GetNames(typeof(Mode)),
GUILayout.Height(ToolBarRect.height));
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.EndArea();
Handles.EndGUI();
}
}
這將直接在 SceneView 中顯示工具欄
以下是你可以走多遠的快速一瞥: