Unity编辑器扩展--Create Custom Inspector
一、Create Custom Inspector
重绘inspector面板一方面是我们的挂在脚本的窗口变得友好,另一方面可以让其变得更强大,比如添加一些有效性验证。
二、重要说明
EditorUtility.SetDirty(object target)
:该方法可以表明target对象为dirty((⊙﹏⊙)b,怎么翻译合适?)的,unity会将有dirty标记的已经改变的对象在磁盘中存储,可以用来对一些修改数据的强制刷新,这里用来立即绘制GUI(我们对GUI的修改不会立即生效,只有鼠标在Scene上时才会强制重绘界面元素)。- 对于类似
GUI.Style
等静态属性的修改,在修改前需要备份,使用后在设回,避免修改后的对其他无需使用修改后属性的干扰。 - 布局中的
GUILayout.BeginVertical
等需成对出现,有始有终。 - 该类型的脚本都需放在Editor文件夹下,unity会自动调用。
三、Code
using UnityEngine;
using System.Collections;
using UnityEditor;
namespace RunAndJump.LeveCreator
{
//[CanEditMultipleObjects] //希望多个挂在该类的对象可以在inspector面板选定多个一同修改的话
//需要将该标签添加上,由于level类一个场景下只有一个,所以无需添加该标记
[CustomEditor(typeof(Level))]
public class LevelInspector : Editor
{
private Level _myTarget;
private int _newTotalColumns;
private int _newTotalRows;
private void OnEnable()
{
Debug.Log("OnEnable was called...");
_myTarget = (Level)target;
InitLevel();
ResetResizeValues();
}
private void OnDisable()
{
Debug.Log("OnDisable was called...");
}
private void OnDestory()
{
Debug.Log("OnDestroy was called...");
}
public override void OnInspectorGUI()
{
EditorGUILayout.LabelField("The GUI of this inspector was modified.");
EditorGUILayout.LabelField("The current level time is:"+_myTarget.TotalTime);
// DrawDefaultInspector();//使用unity默认的绘制方式来显示Inspector面板
DrawDateGUI();
DrawLevelSizeGUI();
//当使用绘制面板方法并且GUI改变时刷新GUI页面
if(GUI.changed)
EditorUtility.SetDirty(_myTarget);
}
private void DrawLevelSizeGUI()
{
EditorGUILayout.LabelField("Size",EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal("box");
EditorGUILayout.BeginVertical();
_newTotalColumns = EditorGUILayout.IntField("Columns", Mathf.Max(0, _newTotalColumns));
_newTotalRows = EditorGUILayout.IntField("Rows", Mathf.Max(0, _newTotalRows));
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical();
bool oldEnable = GUI.enabled;
GUI.enabled = (_newTotalColumns != _myTarget.TotalColumns || _newTotalRows != _myTarget.TotalRows);
bool buttonResize = GUILayout.Button("Resize", GUILayout.Height(2*EditorGUIUtility.singleLineHeight));
if (buttonResize)
{
if (EditorUtility.DisplayDialog(
"Level Creator",
"Are you sure you want to resize the leve?\nThis action cannot be undone",
"yes",
"no"
))
{
ResizeLeve();
}
}
bool buttonReset = GUILayout.Button("Reset");
if (buttonReset)
{
ResetResizeValues();
}
GUI.enabled = oldEnable;
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
}
private void InitLevel()
{
if (_myTarget.Pieces == null || _myTarget.Pieces.Length == 0)
{
Debug.Log("Initializing thie Pieces array...");
_myTarget.Pieces=new LevelPiece[_myTarget.TotalColumns*_myTarget.TotalRows];
}
}
private void ResetResizeValues()
{
_newTotalColumns = _myTarget.TotalColumns;
_newTotalRows = _myTarget.TotalRows;
}
private void ResizeLeve()
{
LevelPiece[] newPieces=new LevelPiece[_newTotalColumns*_newTotalRows];
for (int col = 0; col < _myTarget.TotalColumns; ++col)
{
for (int row = 0; row < _myTarget.TotalRows; ++row)
{
if (col < _newTotalColumns && row < _newTotalRows)
{
newPieces[col + row*_newTotalColumns] = _myTarget.Pieces[col + row*_myTarget.TotalColumns];
}
else
{
LevelPiece piece = _myTarget.Pieces[col+row*_myTarget.TotalColumns];
if (piece != null)
{
//在editor模式下我们必须使用DestroyImmediate
Object.DestroyImmediate(piece.gameObject);
}
}
}
}
_myTarget.Pieces = newPieces;
_myTarget.TotalColumns = _newTotalColumns;
_myTarget.TotalRows = _newTotalRows;
}
private void DrawDateGUI()
{
EditorGUILayout.LabelField("Data",EditorStyles.boldLabel);
EditorGUILayout.BeginVertical("box");
_myTarget.TotalTime = EditorGUILayout.IntField("Total Time", Mathf.Max(0, _myTarget.TotalTime));
_myTarget.Gravity = EditorGUILayout.FloatField("Gravity", _myTarget.Gravity);
_myTarget.Bgm = (AudioClip) EditorGUILayout.ObjectField("Bgm", _myTarget.Bgm, typeof (AudioClip), false);
_myTarget.Background =
(Sprite) EditorGUILayout.ObjectField("Background", _myTarget.Background, typeof (Sprite), false);
EditorGUILayout.EndVertical();
}
}
}
四、效果
前:后: