本文讲的是在编辑状态下,对Scene界面的一些UI操作。作用在于地编,或者把一些繁琐的东西做个编辑界面给策划自己去设计。先上效果图:
首先,在场景任意物体上挂上你的MONO脚本,具体脚本实现什么功能自行设计。
这里我们简单在灯光下面挂一个MyGraph脚本。
public class MyGraph : MonoBehaviour
{
public Transform cube;
}
然后就是响应问题,我们怎么实现图中一点击灯光,就弹出对应的UI呢。这里需要用到[CustomEditor]和OnSceneGUI()。
我们创建一个MyGraphEditor类,它需要继承Editor,并且在开头加上[CustomEditor(typeof(MyGraph))]。
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine.SceneManagement;
[CustomEditor(typeof(MyGraph))]
public class MyGraphEditor : Editor
{
private bool _linkMode;
private MyGraph m_graph;
private Transform cube;
private SerializedObject test;
private void Awake()
{
Debug.Log("Init");
m_graph = target as MyGraph;
test = new SerializedObject(target);
cube = m_graph.cube;
}
}
这里的[CustomEditor(typeof(MyGraph))],起到的就是和挂载在物体上的MyGraph脚本关联的作用。
而Awake方法,会在用户每次点击挂载物体时执行。
里边写了两个比较常用的变量。
m_graph可以通过target变量强转获取,也就是脚本本身。而target是继承了Editor后的自带变量。
test是SerializedObject类型的变量,同样可以通过target初始化得到,它可以理解为你当前挂载脚本的序列化对象。这个在后面会用到。同样,也可以直接通过serializedObject变量获取,也是Editor自带,和test相同。
接下来,就是我们要编辑的UI界面了。
private void OnSceneGUI()
{
serializedObject.Update();
Handles.BeginGUI();
GUILayout.BeginVertical("Graph Tools", "window", new[] { GUILayout.Height(500), GUILayout.Width(120) });
var buttonStyle = new[] { GUILayout.Height(30), GUILayout.Width(100) };
var linkMode = _linkMode;
linkMode = GUILayout.Toggle(linkMode, "Link", "button", buttonStyle);
linkMode = !GUILayout.Toggle(!linkMode, "Move", "button", buttonStyle);
_linkMode = linkMode;
GUILayout.Space(10);
if (GUILayout.Button("Add Point", buttonStyle))
{
}
if (GUILayout.Button("Del Point", buttonStyle))
{
}
GUILayout.EndVertical();
Handles.EndGUI();
}
其实里边的内容就很简单了,就是最基本的原始GUILayout的一些操作。这里用到了window,toggle,button,到此,UI的显示就实现了。
最后一个小功能,就是图中所示的拖动一个小方块,改变Cube的位置,进行连线。这里用到了HandleUtility类,引用盛典的说法:控制柄工具。Handles.Slider2D,这将在屏幕上绘制一个可拖动控制柄。然后每次移动,把新的位置赋值给slider.
这里就不多说Handle的用法了,直接上代码,不懂得地方可以询问.继续在OnSceneGUI中加入以下代码:
private void OnSceneGUI()
{
Handles.color = Color.red;
var postion = cube.position;
var size = HandleUtility.GetHandleSize(PosTarget) * 0.3f;
var pos= Handles.Slider2D(
postion, Vector3.forward,
Vector3.up, Vector3.right,
size, Handles.CubeHandleCap, Vector2.one);
if (pos != PosTarget)
{
EditorUtility.SetDirty(target);
EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
}
postion = pos;
Handles.Slider2D(
Vector3.zero, Vector3.forward,
Vector3.up, Vector3.right,
size, Handles.CylinderHandleCap, Vector2.one);
cube.position = postion;
Handles.DrawLine(Vector3.zero, postion);
HandleUtility.Repaint();
}
通过Hander.DrawLine将两个点连接。还有一点,是这里有一个OnInspectorGUI方法,可以重构Inspector界面中该类的显示。这和上一篇讲到的Inspector类似,在此就略过。