25.Inspector窗口拓展-自定义数据
25.1 知识点
自定义属性 在Inspector窗口显示 基础方式
主要知识点:
EditorGUILayout.PropertyField(SerializedProperty对象, 标题);
该API会按照属性类型自己去处理控件绘制的逻辑。
声明自定义数据类,需要序列化特性
using System;
[Serializable]
public class TestCustomClass
{
public int i;
public float f;
}
自定义脚本中声明自定义数据类变量
public TestCustomClass myCustom;
编辑器脚本中使用Unity自带的显示方式
private SerializedProperty myCustom;
private void OnEnable()
{
myCustom = serializedObject.FindProperty("myCustom");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(myCustom, new GUIContent("我的自定义属性"));
serializedObject.ApplyModifiedProperties();
}
代码效果
自定义属性 在Inspector窗口显示 自定义方式
如果我们不想要Unity默认的绘制方式去显示自定义数据结构类相关内容,我们也可以完全自定义布局方式。主要知识点:
SerializedProperty.FindPropertyRelative(属性)
serializedObject.FindProperty(属性.子属性)
自定义显示数据结构类中的变量
private SerializedProperty myCustom;
private SerializedProperty myCustomI;
private SerializedProperty myCustomF;
private void OnEnable()
{
myCustom = serializedObject.FindProperty("myCustom");
// 以下两种方式二选其一
// myCustomI = myCustom.FindPropertyRelative("i");
// myCustomF = myCustom.FindPropertyRelative("f");
myCustomI = serializedObject.FindProperty("myCustom.i");
myCustomF = serializedObject.FindProperty("myCustom.f");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(myCustom, new GUIContent("我的自定义属性"));
myCustomI.intValue = EditorGUILayout.IntField("自定义属性中的I", myCustomI.intValue);
myCustomF.floatValue = EditorGUILayout.FloatField("自定义属性中的F", myCustomF.floatValue);
serializedObject.ApplyModifiedProperties();
}
代码效果
两个变量指向的是同一份内存,改动其中一个会实时同步
25.2 知识点代码
Lesson25_Inspector窗口拓展_自定义数据
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson25_Inspector窗口拓展_自定义数据 : MonoBehaviour
{
void Start()
{
#region 知识点一 自定义属性 在Inspector窗口显示 基础方式
//主要知识点:
//EditorGUILayout.PropertyField(SerializedProperty对象, 标题);
//该API会按照属性类型自己去处理控件绘制的逻辑
#endregion
#region 知识点二 自定义属性 在Inspector窗口显示 自定义方式
//如果我们不想要Unity默认的绘制方式去显示 自定义数据结构类 相关内容
//我们也可以完全自定义布局方式
//主要知识点:
//1.SerializedProperty.FindPropertyRelative(属性)
//2.serializedObject.FindProperty(属性.子属性)
#endregion
}
}
TestCustomClass
using System;
[Serializable]
public class TestCustomClass
{
public int i;
public float f;
}
TestInspectorMono
using System.Collections.Generic;
using UnityEngine;
public class TestInspectorMono : MonoBehaviour
{
#region Lesson23_Inspector窗口拓展_基础知识
//攻击力
public int atk;
//防御力
public float def;
//敌对目标对象依附的Gameobject
public GameObject obj;
#endregion
#region Lesson24_Inspector窗口拓展_数组List
public string[] strs;
public int[] ints;
public GameObject[] gameObjects;
public List<GameObject> listObjs;
#endregion
#region Lesson25_Inspector窗口拓展_自定义数据
public TestCustomClass myCustom;
#endregion
}
TestInspectorMonoEditor
using UnityEditor;
using UnityEngine;
//通过这个特性,我们就可以为TestInspectorMono脚本自定义Inspector窗口中的显示了
[CustomEditor(typeof(TestInspectorMono))]
public class TestInspectorMonoEditor : Editor
{
#region Lesson23_Inspector窗口拓展_基础知识
private SerializedProperty atk;
private SerializedProperty def;
private SerializedProperty obj;
private bool foldOut;
#endregion
#region Lesson24_Inspector窗口拓展_数组和List
private SerializedProperty strs;
private SerializedProperty ints;
private SerializedProperty gameObjects;
private SerializedProperty listObjs;
private int count;
private bool arrayAndListFoldOut;
#endregion
#region Lesson25_Inspector窗口拓展_自定义数据
private SerializedProperty myCustom;
private SerializedProperty myCustomI;
private SerializedProperty myCustomF;
#endregion
private void OnEnable()
{
#region Lesson23_Inspector窗口拓展_基础知识
//这样就得到与测试脚本对应的字段
atk = serializedObject.FindProperty("atk");
def = serializedObject.FindProperty("def");
obj = serializedObject.FindProperty("obj");
#endregion
#region Lesson24_Inspector窗口拓展_数组和List
//默认得到的数组和List容量为空
strs = serializedObject.FindProperty("strs");
ints = serializedObject.FindProperty("ints");
gameObjects = serializedObject.FindProperty("gameObjects");
listObjs = serializedObject.FindProperty("listObjs");
//初始化当前容量 否则 每次一开始都是0
count = listObjs.arraySize;
#endregion
#region Lesson25_Inspector窗口拓展_自定义数据
myCustom = serializedObject.FindProperty("myCustom");
//以下两种方式二选其一
//myCustomI = myCustom.FindPropertyRelative("i");
//myCustomF = myCustom.FindPropertyRelative("f");
myCustomI = serializedObject.FindProperty("myCustom.i");
myCustomF = serializedObject.FindProperty("myCustom.f");
#endregion
}
public override void OnInspectorGUI()
{
//base.OnInspectorGUI();//注释掉父类调用后,Inspector窗口默认显示的atk def obj会消失
serializedObject.Update();
#region Lesson23_Inspector窗口拓展_基础知识
foldOut = EditorGUILayout.BeginFoldoutHeaderGroup(foldOut, "基础属性");
if (foldOut)
{
GUILayout.Button("测试自定义Inspector窗口");
EditorGUILayout.IntSlider(atk, 0, 100, "攻击力");
def.floatValue = EditorGUILayout.FloatField("防御力", def.floatValue);
EditorGUILayout.ObjectField(obj, new GUIContent("敌对对象"));
if (GUILayout.Button("打印当前target对象"))
{
Debug.Log("组件类型" + target.GetType());
Debug.Log("组件依附的游戏对象名" + target.name);
}
}
EditorGUILayout.EndFoldoutHeaderGroup();
#endregion
#region Lesson24_Inspector窗口拓展_数组和List
EditorGUILayout.PropertyField(strs, new GUIContent("字符串数组"));
EditorGUILayout.PropertyField(ints, new GUIContent("整形数组"));
EditorGUILayout.PropertyField(gameObjects, new GUIContent("游戏对象数组"));
// EditorGUILayout.PropertyField(listObjs, new GUIContent("游戏对象List"));
arrayAndListFoldOut = EditorGUILayout.BeginFoldoutHeaderGroup(arrayAndListFoldOut, "数组和List属性");
if (arrayAndListFoldOut)
{
//容量设置
count = EditorGUILayout.IntField("List容量", count);
//是否要缩减 移除尾部的内容
//从后往前去移除 避免移除不干净
//当容量变少时 才会走这的逻辑
for (int i = listObjs.arraySize - 1; i >= count; i--)
listObjs.DeleteArrayElementAtIndex(i);
//根据容量绘制需要设置的每一个索引位置的对象
for (int i = 0; i < count; i++)
{
//去判断如果数组或者LIst容量不够 去通过插入的形式去扩容
if (listObjs.arraySize <= i)
listObjs.InsertArrayElementAtIndex(i);
SerializedProperty indexPro = listObjs.GetArrayElementAtIndex(i);
EditorGUILayout.ObjectField(indexPro, new GUIContent($"索引{i}"));
}
}
EditorGUILayout.EndFoldoutHeaderGroup();
#endregion
#region Lesson25_Inspector窗口拓展_自定义数据
EditorGUILayout.PropertyField(myCustom, new GUIContent("我的自定义属性"));
myCustomI.intValue = EditorGUILayout.IntField("自定义属性中的I", myCustomI.intValue);
myCustomF.floatValue = EditorGUILayout.FloatField("自定义属性中的F", myCustomF.floatValue);
#endregion
serializedObject.ApplyModifiedProperties();
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com