我一直在寻找新的方法来改进Unity编辑器中的编辑。 我的项目中的一个常见问题是:简化定义代表场景中某个点的序列化字段(即序列化Vector3)的坐标
例如,假设我有一个脚本可以在场景中的某个位置生成某个预制件:
- 里斯果酱之屋
- 狮子窝里的老鼠:我的第一个游戏果酱
- Danki Code-游戏解散游戏| Criado Por DankiCode
- Pygame教程#1:在窗口中显示渲染的文本。
- 生存规则(ROS)– cictwvsu-在线–中
using UnityEngine;
using System.Collections;public class ExampleBehavior : MonoBehaviour {
public Vector3 SpawnPosition;
public GameObject SpawnableObject;public void Spawn() {
Instantiate(SpawnableObject, SpawnPosition, Quaternion.identity);
}
}
我的目标是SpawnPosition
在场景内移动SpawnPosition
点的过程。
我的第一种方法是使用OnGizmosSelected
方法(在场景编辑器中显示一个彩色球体)来指示点位置,然后手动更改Vector3的值,直到获得正确的位置。 但是编辑起来不是很舒服。
检查了这个很棒的插件源之后,我发现了Unity Editor的Handles API,这是在场景中产生可交互对象(例如点,可调整大小的形状等)的一组方法。
因此,我尝试定义一个自定义编辑器脚本以在通用点上显示一个Handle
,以便可以轻松地在许多脚本中重用它。
这是我的做法:
首先,我定义了一个新的PropertyAttribute
,因此可以使用它在编辑器上启用此行为:
public class DraggablePoint : PropertyAttribute {}
然后,我为所有MonoBehaviors
定义了一个自定义编辑器脚本,该脚本将迭代每个属性以搜索DraggablePoint
,并显示其句柄:
[CustomEditor(typeof(MonoBehaviour), true)]
public class DraggablePointDrawer : Editor {[CustomEditor(typeof(MonoBehaviour), true)]
public class DraggablePointDrawer : Editor {readonly GUIStyle style = new GUIStyle();
void OnEnable(){
style.fontStyle = FontStyle.Bold;
style.normal.textColor = Color.white;
}void OnEnable(){
style.fontStyle = FontStyle.Bold;
style.normal.textColor = Color.white;
}public void OnSceneGUI () {
var property = serializedObject.GetIterator ();
while (property.Next (true)) {
if (property.propertyType == SerializedPropertyType.Vector3) {
var field = serializedObject.targetObject.GetType ().GetField (property.name);
if (field == null) {
continue;
}
var draggablePoints = field.GetCustomAttributes (typeof(DraggablePoint), false);
if (draggablePoints.Length > 0) {
Handles.Label(property.vector3Value, property.name);
property.vector3Value = Handles.PositionHandle (property.vector3Value, Quaternion.identity);
serializedObject.ApplyModifiedProperties ();
}
}
}
}
}public void OnSceneGUI () {
var property = serializedObject.GetIterator ();
while (property.Next (true)) {
if (property.propertyType == SerializedPropertyType.Vector3) {
var field = serializedObject.targetObject.GetType ().GetField (property.name);
if (field == null) {
continue;
}
var draggablePoints = field.GetCustomAttributes (typeof(DraggablePoint), false);
if (draggablePoints.Length > 0) {
Handles.Label(property.vector3Value, property.name);
property.vector3Value = Handles.PositionHandle (property.vector3Value, Quaternion.identity);
serializedObject.ApplyModifiedProperties ();
}
}
}
}
}
注意:
- 我将
true
作为第二个参数传递给CustomEditor
。 这是为了统一地将此编辑器脚本实例化到继承自MonoBehavior(每个统一脚本组件)的所有类。 - 我正在使用
serializedObject.GetIterator ()
对脚本的每个属性进行迭代。 - 我使用反射来检查在当前对象属性中定义的
DraggableType
类型的任何PropertyAttribute
。 - 我使用
serializedObject.ApplyModifiedProperties ();
应用手柄完成的运动。 它还会创建一个历史记录条目,因此您可以使用ctrl+z
回滚运动
我认为结果非常酷!
这是一个例子:

这是完整的代码示例:
https://gist.github.com/ProGM/226204b2a7f99998d84d755ffa1fb39a
我正在为电子游戏使用此脚本。 一探究竟!
希望您能发现它有用!