家具网站建设规划,wordpress分享qq,网络推广有哪些形式,手机app开发工资高吗文章目录 1 SerializedObject 和 SerializedProperty2 自定义显示步骤3 数组、List 自定义显示3.1 基础方式3.2 自定义方式 4 自定义属性自定义显示4.1 基础方式4.2 自定义方式 5 字典自定义显示5.1 SerizlizeField5.2 ISerializationCallbackReceiver5.3 代码示例 1 Serialize… 文章目录 1 SerializedObject 和 SerializedProperty2 自定义显示步骤3 数组、List 自定义显示3.1 基础方式3.2 自定义方式 4 自定义属性自定义显示4.1 基础方式4.2 自定义方式 5 字典自定义显示5.1 SerizlizeField5.2 ISerializationCallbackReceiver5.3 代码示例 1 SerializedObject 和 SerializedProperty
在 Unity 中可以完全自定义某一个脚本在 Inspector 窗口的相关显示。
SerializedObject 和 SerializedProperty 主要用于在 Unity 编辑器中操作和修改序列化对象的属性通常在自定义编辑器中使用以创建更灵活、可定制的属性面板。
只需记住简单的规则 SerializedObject代表脚本对象。 参考文档https://docs.unity.cn/cn/2022.1/ScriptReference/SerializedObject.html。 SerializedProperty代表脚本对象中的属性。 参考文档https://docs.unity.cn/cn/2022.1/ScriptReference/SerializedProperty.html。
2 自定义显示步骤 单独为某一个脚本实现一个自定义脚本并且脚本需要继承 Editor。 一般该脚本命名为自定义脚本名 Editor。 在该脚本前加上特性。 命名空间UnityEditor 特性名CustomEditor想要自定义脚本类名的 Type
using UnityEditor;
using UnityEngine;// 通过该特性可以为 Lesson22 脚本自定义 Inspector 窗口中的显示
[CustomEditor(typeof(Lesson22))]
public class Lesson22Editor : Editor
{...
}声明对应 SerializedProperty 序列化属性对象主要通过它和自定义脚本中的成员进行关联。 可以利用继承 Editor 后的成员 serializedObject 中的 FindProperty(成员变量名) 方法关联对应成员。 一般在 OnEnable 函数中初始化。当选中对象后并在 Inspector 窗口进行显示时OnEnable 函数会被执行同理选择其他对象使 Inspector 窗口取消显示时OnDisable 函数会被执行。
using UnityEditor;
using UnityEngine;// 通过该特性可以为 Lesson22 脚本自定义 Inspector 窗口中的显示
[CustomEditor(typeof(Lesson22))]
public class Lesson22Editor : Editor
{private SerializedProperty atk;private SerializedProperty def;private SerializedProperty obj;private void OnEnable() {// 关联序列化属性atk serializedObject.FindProperty(atk);def serializedObject.FindProperty(def);obj serializedObject.FindProperty(obj);}
}重写 OnInspectorGUI 函数。 该函数控制 Inspector 窗口中显示的内容只需在其中重写内容便可自定义窗口。 注意其中的逻辑需要包裹在这两句代码之间 serializedObject.Update(); // 更新序列化对象的表示形式 ... serializedObject.ApplyModifiedProperties(); // 应用属性修改
using UnityEditor;
using UnityEngine;// 通过该特性可以为 Lesson22 脚本自定义 Inspector 窗口中的显示
[CustomEditor(typeof(Lesson22))]
public class Lesson22Editor : Editor
{private SerializedProperty atk;private SerializedProperty def;private SerializedProperty obj;private bool foldOut;private void OnEnable() {// 关联序列化属性atk serializedObject.FindProperty(atk);def serializedObject.FindProperty(def);obj serializedObject.FindProperty(obj);}// 该函数控制了 Inspector 窗口中显示的内容// 只需要在其中重写内容便可以自定义窗口public override void OnInspectorGUI() {// base.OnInspectorGUI(); 不要调用父类的方法而是去自定义serializedObject.Update(); // 更新序列化对象的表示形式// 自定义Inspector窗口的内容foldOut EditorGUILayout.BeginFoldoutHeaderGroup(foldOut, 基础属性);if (foldOut) {if (GUILayout.Button(测试自定义 Inspector 窗口)) {Debug.Log(target.name); // 获取 Lesson22 脚本对象}EditorGUILayout.IntSlider(atk, 0, 100, 攻击力);def.floatValue EditorGUILayout.FloatField(防御力, def.floatValue);EditorGUILayout.ObjectField(obj, new GUIContent(敌对对象));}EditorGUILayout.EndFoldoutHeaderGroup();serializedObject.ApplyModifiedProperties(); // 应用属性修改}
}3 数组、List 自定义显示
3.1 基础方式
EditorGUILayout.PropertyField(SerializedProperty对象, 标题);
该 API 会按照属性类型默认处理控件绘制的逻辑。
using UnityEditor;
using UnityEngine;// 通过该特性可以为 Lesson22 脚本自定义 Inspector 窗口中的显示
[CustomEditor(typeof(Lesson22))]
public class Lesson22Editor : Editor
{private SerializedProperty strs;private SerializedProperty ints;private SerializedProperty gameObjects;private SerializedProperty listObjs;private void OnEnable() {// 默认得到的数组和 List 容量为空strs serializedObject.FindProperty(strs);ints serializedObject.FindProperty(ints);gameObjects serializedObject.FindProperty(gameObjects);listObjs serializedObject.FindProperty(listObjs);}public override void OnInspectorGUI() {serializedObject.Update();EditorGUILayout.PropertyField(strs, new GUIContent(字符串数组));EditorGUILayout.PropertyField(ints, new GUIContent(整形数组));EditorGUILayout.PropertyField(gameObjects, new GUIContent(游戏对象数组));EditorGUILayout.PropertyField(listObjs, new GUIContent(游戏对象List));serializedObject.ApplyModifiedProperties();}
}3.2 自定义方式
利用 SerializedProperty 中数组相关的 API 来完成自定义。
API说明arraySize获取数组或 List 容量。InsertArrayElementAtIndex(索引)为数组在指定索引插入默认元素容量会变化。DeleteArrayElementAtIndex(索引)为数组在指定索引删除元素容量会变化。GetArrayElementAtIndex(索引)获取数组中指定索引位置的 SerializedProperty 对象。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;// 通过该特性可以为 Lesson22 脚本自定义 Inspector 窗口中的显示
[CustomEditor(typeof(Lesson22))]
public class Lesson22Editor : Editor
{private SerializedProperty strs;private SerializedProperty ints;private SerializedProperty gameObjects;private SerializedProperty listObjs;private int count;private void OnEnable() {// 默认得到的数组和 List 容量为空strs serializedObject.FindProperty(strs);ints serializedObject.FindProperty(ints);gameObjects serializedObject.FindProperty(gameObjects);listObjs serializedObject.FindProperty(listObjs);// 初始化当前容量否则每次开始都是 0count listObjs.arraySize;}public override void OnInspectorGUI() {serializedObject.Update();// 容量设置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}));}serializedObject.ApplyModifiedProperties();}
}4 自定义属性自定义显示
4.1 基础方式
EditorGUILayout.PropertyField(SerializedProperty对象, 标题);
需要为自定义类添加 Serializable 特性。
using System;
using UnityEngine;[Serializable]
public class MyCustomPro
{public int i;public float f;
}public class Lesson22 : MonoBehaviour
{public MyCustomPro myCustom;
}using UnityEditor;
using UnityEngine;[CustomEditor(typeof(Lesson22))]
public class Lesson22Editor : Editor
{private SerializedProperty myCustom;private void OnEnable() {myCustom serializedObject.FindProperty(myCustom);}public override void OnInspectorGUI() {serializedObject.Update();EditorGUILayout.PropertyField(myCustom, new GUIContent(我的自定义属性));serializedObject.ApplyModifiedProperties();}
}4.2 自定义方式
使用如下方法寻找自定义属性的成员
SerializedProperty.FindPropertyRelative(属性)SerializedObject.FindProperty(属性.子属性)
using UnityEditor;
using UnityEngine;[CustomEditor(typeof(Lesson22))]
public class Lesson22Editor : Editor
{private SerializedProperty myCustomI;private SerializedProperty myCustomF;private void OnEnable() {// myCustomI myCustom.FindPropertyRelative(i);// myCustomF myCustom.FindPropertyRelative(f);myCustomI serializedObject.FindProperty(myCustom.i);myCustomF serializedObject.FindProperty(myCustom.f);}public override void OnInspectorGUI() {serializedObject.Update();myCustomI.intValue EditorGUILayout.IntField(自定义属性中的I, myCustomI.intValue);myCustomF.floatValue EditorGUILayout.FloatField(自定义属性中的F, myCustomF.floatValue);serializedObject.ApplyModifiedProperties();}
}5 字典自定义显示
5.1 SerizlizeField
SerizlizeField 特性让私有字段可以被序列化能够在 Unity 的 Inspector 窗口被看到。
5.2 ISerializationCallbackReceiver
该接口是 Unity 用于序列化和反序列化时执行自定义逻辑的接口实现该接口的类能够在对象被序列化到磁盘或从磁盘反序列化时执行一些额外代码。
接口中函数
OnBeforeSerialize: 在对象被序列化之前调用。OnAfterDeserialize: 在对象从磁盘反序列化后调用。
由于需要用两个 List 存储 Dictionary 的键值对所以需要在
OnBeforeSerialize 序列化之前将 Dictionary 里的数据存入 List 中进行序列化。OnAfterDeserialize 反序列化之后将 List 中反序列化出来的数据存储到 Dictionary 中。
5.3 代码示例
using System.Collections.Generic;
using UnityEngine;public class Lesson22 : MonoBehaviour, ISerializationCallbackReceiver
{public Dictionaryint, string myDic new Dictionaryint, string() { { 1, 123 }, { 2, 234 } };[SerializeField]private Listint keys new Listint();[SerializeField]private Liststring values new Liststring();public void OnAfterDeserialize() {myDic.Clear();for (int i 0; i keys.Count; i) {if (!myDic.ContainsKey(keys[i]))myDic.Add(keys[i], values[i]);elseDebug.LogWarning(字典Dictionary容器中不允许有相同的键);}}public void OnBeforeSerialize() {keys.Clear();values.Clear();foreach (var item in myDic) {keys.Add(item.Key);values.Add(item.Value);}}
}using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;[CustomEditor(typeof(Lesson22))]
public class Lesson22Editor : Editor
{private SerializedProperty keys;private SerializedProperty values;private int dicCount;private void OnEnable() {keys serializedObject.FindProperty(keys);values serializedObject.FindProperty(values);dicCount keys.arraySize;}public override void OnInspectorGUI() {serializedObject.Update();dicCount EditorGUILayout.IntField(字典容量, dicCount);// 容量变少时把多的删了for (int i keys.arraySize - 1; i dicCount; i--) {keys.DeleteArrayElementAtIndex(i);values.DeleteArrayElementAtIndex(i);}for (int i 0; i dicCount; i) {// 如果容量不够扩容if (keys.arraySize i) {keys.InsertArrayElementAtIndex(i);values.InsertArrayElementAtIndex(i);}// 自定义键值对的修改SerializedProperty indexKey keys.GetArrayElementAtIndex(i);SerializedProperty indexValue values.GetArrayElementAtIndex(i);EditorGUILayout.BeginHorizontal();indexKey.intValue EditorGUILayout.IntField(字典的键, indexKey.intValue);indexValue.stringValue EditorGUILayout.TextField(字典的值, indexValue.stringValue);EditorGUILayout.EndHorizontal();}serializedObject.ApplyModifiedProperties();}
}