24.Inspector窗口拓展-数组和List
24.1 知识点
数组、List属性在Inspector窗口显示 基础方式
主要知识点:
- EditorGUILayout.PropertyField(SerializedProperty对象, 标题)
- 该API会按照属性类型自己去处理控件绘制的逻辑。
在自定义脚本添加数组List相关变量
public string[] strs;
public int[] ints;
public GameObject[] gameObjects;
public List<GameObject> listObjs;
在编辑器脚本获得后绘制
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();
}
注意:
因为数组和List自带折叠,放到我们自定义的折叠代码中会报错。
//以下代码会报错
arrayAndListFoldOut = EditorGUILayout.BeginFoldoutHeaderGroup(arrayAndListFoldOut, "数组和List属性");
if (arrayAndListFoldOut)
{
EditorGUILayout.PropertyField(strs, new GUIContent("字符串数组"));
EditorGUILayout.PropertyField(ints, new GUIContent("整形数组"));
EditorGUILayout.PropertyField(gameObjects, new GUIContent("游戏对象数组"));
EditorGUILayout.PropertyField(listObjs, new GUIContent("游戏对象List"));
}
代码效果
数组、List属性在Inspector窗口显示 自定义方式
如果我们不想要Unity默认的绘制方式去显示数组、List相关内容,我们也可以完全自定义布局方式。
主要知识点:
- 利用SerializedProperty中数组相关的API来完成自定义
- arraySize 获取数组或List容量
- InsertArrayElementAtIndex(索引) 为数组在指定索引插入默认元素(容量会变化)
- DeleteArrayElementAtIndex(索引) 为数组在指定索引删除元素(容量会变化)
- GetArrayElementAtIndex(索引) 获取数组中指定索引位置的 SerializedProperty 对象
自定义List显示,可以放入折叠代码中。输入容量更新List长度。每次初始化根据List长度得到容量,否则每次一开始都是0。当容量更新是判断是否要删除或补充新的元素
private SerializedProperty listObjs;
private int count;
private bool arrayAndListFoldOut;
private void OnEnable()
{
// 默认得到的数组和List容量为空
listObjs = serializedObject.FindProperty("listObjs");
// 初始化当前容量 否则 每次一开始都是0
count = listObjs.arraySize;
}
public override void OnInspectorGUI()
{
// 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();
}
代码效果
24.2 知识点代码
Lesson24_Inspector窗口拓展_数组和List
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson24_Inspector窗口拓展_数组和List : MonoBehaviour
{
void Start()
{
#region 知识点一 数组、List属性在Inspector窗口显示 基础方式
//主要知识点:
//EditorGUILayout.PropertyField(SerializedProperty对象, 标题);
//该API会按照属性类型自己去处理控件绘制的逻辑
#endregion
#region 知识点二 数组、List属性在Inspector窗口显示 自定义方式
//如果我们不想要Unity默认的绘制方式去显示 数组、List相关内容
//我们也可以完全自定义布局方式
//主要知识点:
//利用SerializedProperty中数组相关的API来完成自定义
//1.arraySize 获取数组或List容量
//2.InsertArrayElementAtIndex(索引) 为数组在指定索引插入默认元素(容量会变化)
//3.DeleteArrayElementAtIndex(索引) 为数组在指定索引删除元素(容量会变化)
//4.GetArrayElementAtIndex(索引) 获取数组中指定索引位置的 SerializedProperty 对象
#endregion
}
}
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
}
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
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
}
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
serializedObject.ApplyModifiedProperties();
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com