这篇文章由爱发电支持写作, 如果你喜欢我做的事情,可以考虑在那里支持我。
Unity里面比较出色我也很喜欢的一个功能就是它易于拓展的编辑器。一般来说拓展编辑器对于游戏运行效率不是有什么大的帮助,但是有助于开发效率的提高。
毕竟工欲善其事,必先利其器。
这次介绍一共以下这些拓展编辑器的方法:OnDrawGizmos
OnInspectorGUI
OnSceneGUI
MenuItem 与 EditorWindow
ScriptableWizard
ScriptObject
Attributes
AssetProcess
OnDrawGizmos
OnDrawGizmos是在MonoBehaviour下的一个方法,通过这个方法可以可以绘制出一些Gizmos来使得其一些参数方便在Scene窗口查看。
比如我们有一个沿着路点移动的平台,一般的操作可能是生成一堆新的子物体来确定和设置位置,但其实这样会有点赘余,我们需要的只是一个Vector2/Vector3数组。而这个时候我们就可以通过OnDrawGizmos方法在编辑器绘制出这些Vector2/Vector3的数组点。
完整代码如下:
public class DrawGizmoTest : MonoBehaviour
{
public Vector2[] poses;
private void OnDrawGizmos()
{
Color originColor = Gizmos.color;
Gizmos.color = Color.red;
if( poses!=null && poses.Length>0 )
{
//Draw Sphere for (int i = 0; i < poses.Length; i++)
{
Gizmos.DrawSphere( poses[i], 0.2f );
}
//Draw Line Gizmos.color = Color.yellow;
Vector2 lastPos = Vector2.zero;
for (int i = 0; i < poses.Length; i++)
{
if( i > 0 )
{
Gizmos.DrawLine( lastPos, poses[i] );
}
lastPos = poses[i];
}
}
Gizmos.color = originColor;
}
}
OnInspectorGUI
在开发过程中常常需要在编辑器上对某个特定的Component进行一些操作,比如在Inspector界面上有一个按钮可以触发一段代码。
这种属于编辑器的,所以一般是在Editor文件夹中新建一个继承自Editor的脚本:
之后编辑继承自UnityEditor.Editor,这里注意是必须在类上加入[CustomEditor(typeof(编辑器脚本绑定的Monobehavior类)]然后重写它的OnInspectorGUI方法:
using UnityEditor;
[CustomEditor(typeof(InspectorTest))]
public class InspectorTestEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if(GUILayout.Button("Click Me"))
{
//Logic InspectorTest ctr = target as InspectorTest;
}
}
}
而一般而言在Editor类中操作变量有两种方式,一种是通过直接访问或者函数调用改动Monobehaviour的变量,一种是通过Editor类中的serializedObject来改动对应变量。
比如我要把Monobehaviour的一个公开的Name改成Codinggamer
使用方法一,在Editor中可以这样写:
if(GUILayout.Button("Click Me"))
{
//Logic InspectorTest ctr = target as InspectorTest;
ctr.Name = "Codinggamer";
}
在编辑器中点击会发现Hierarchy界面没有出现一般改动之后会出现的小星星:
一般改动是会出现小星星:
如果这个时候你重新打开场景,会发现改动的值又便回原来的值,也就是你的改动并没有生效。
而此时,只需要再调用EditorUtility.SetDirty( Object )方法即可。
如果要使用方法二,则需要在Editor代码中写:
if(GUILayout.Button("Click Me"))
{
//Logic serializedObject.FindProperty("Name").stringValue = "Codinggamer";
serializedObject.ApplyModifiedProperties();
}
这里不需要调用EditorUtility.SetDirty( Object )方法,场景就已经会出现改动之后的小星星,保存重开场景之后也会发现对应值生效。
这两个方法孰优孰劣?
一般来说用第二个方法比较好,但实际上涉及逻辑比较多的时候我是用第一个方法。用第二个方法的好处在于它是内置了撤销功能,也就意味着你调用改动之后是可以直接撤销掉的,而第一个方法就不能。
OnSceneGUI
这个方法也是在Editor类中的一个方法,是用来在Scene视图上显示一个UI元素。其创建也是在Editor文件夹下新建一个继承自Editor的脚本:
在OnSceneGUI中可以做出和OnDrawGizmo类似的功能,比如绘制出Vector2数组的路点:
其代码如下:
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(SceneGUITest))]
public class SceneGUITestEditor : Editor
{
private void OnSceneGU