24.Inspector窗口拓展数组和List

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来完成自定义
    1. arraySize 获取数组或List容量
    2. InsertArrayElementAtIndex(索引) 为数组在指定索引插入默认元素(容量会变化)
    3. DeleteArrayElementAtIndex(索引) 为数组在指定索引删除元素(容量会变化)
    4. 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

×

喜欢就点赞,疼爱就打赏