Unity自定义数组在Inspector窗口的显示方式

了解

  1. 单行高度:EditorGUIUtility.singleLineHeight
  2. 获取 PropertyField 控件所需的高度:EditorGUI.GetPropertyHeight
  3. 属性是否在Inspector窗口展开:SerializedProperty.isExpanded
  4. 可重新排序列表类:ReorderableList
  5. 绘制纯色矩形:EditorGUI.DrawRect

示例

使用版本:2021.3.6f1c1
此版本的Unity已经实现数组元素添加,移除,移动功能。

自定义类

[System.Serializable]
public class Test 
{
    public string name;
    public int age;
}

数据类

定义一个数组,数组元素为自定义类

using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu]
public class TestSO : ScriptableObject
{
    public List<Test> testList;
}

数据类文件默认显示如下

在这里插入图片描述

修改数据类显示

数据元素内容显示为一行

注意:不能使用自动布局api

using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(Test))]
public class TestDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        var spName = property.FindPropertyRelative("name");
        var spAge = property.FindPropertyRelative("age");

        var rect1 = position;
        var rect2 = position;

        var indentlevel = EditorGUI.indentLevel;
        var lableWidth = EditorGUIUtility.labelWidth;
        EditorGUI.indentLevel = 2;
        EditorGUIUtility.labelWidth = 60;

        rect1.width = position.width / 2;
        rect1.height = EditorGUIUtility.singleLineHeight;

        rect2.width = position.width / 2;
        rect2.height = EditorGUIUtility.singleLineHeight;

        rect2.x = position.width / 2+40;
        rect2.y = rect1.y;

        EditorGUI.PropertyField(rect1, spName, new GUIContent("名字"));
        EditorGUI.PropertyField(rect2, spAge, new GUIContent("年龄"));

        EditorGUI.indentLevel = indentlevel;
        EditorGUIUtility.labelWidth = lableWidth;

        //EditorGUI.DrawRect(rect1, Color.green);
        //EditorGUI.DrawRect(rect2, Color.gray);
    }

	//获取属性高度
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return base.GetPropertyHeight(property, label);
    }
}

修改后显示效果如下图所示
在这里插入图片描述

TestList修改为指定名称;Element修改为指定名称

using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(TestSO))]
public class TestSOEditor : Editor
{
    SerializedProperty sPTestList;
    ReorderableList arrayList;

    private void OnEnable()
    {
        sPTestList = serializedObject.FindProperty("testList");

        if (arrayList == null)
        {
            arrayList = new ReorderableList(serializedObject, sPTestList, true, true, true, true);    
            //绘制Header
            arrayList.drawHeaderCallback += DrawHeader;
            //绘制数组元素
            arrayList.drawElementCallback += DrawElement;
            //获取数组的高度
            arrayList.elementHeightCallback += DrawElementHeight;
        }
    }

    void DrawHeader(Rect rect)
    {
        EditorGUI.LabelField(rect, "测试列表");
    }

    void DrawElement(Rect rect, int index, bool isActive, bool isFocused)
    {
        var element = sPTestList.GetArrayElementAtIndex(index);
        var arrowRect = rect;

        int indentLevel = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 1;
        arrowRect.height = EditorGUIUtility.singleLineHeight;
        element.isExpanded = EditorGUI.Foldout(arrowRect, element.isExpanded, new GUIContent("元素" + index));
        EditorGUI.indentLevel = indentLevel;

        //EditorGUI.DrawRect(rect, Color.red);
        //EditorGUI.DrawRect(arrowRect, Color.blue);

        if (element.isExpanded)
        {
            rect.y += arrowRect.height;
            EditorGUI.PropertyField(rect, element);
        }
    }

    float DrawElementHeight(int index)
    {
        var element = sPTestList.GetArrayElementAtIndex(index);
        var height = EditorGUIUtility.singleLineHeight;//折叠箭头的高度   
        if (element.isExpanded)//如果元素展开 获取展开内容的高度和箭头的高度之和
            height += EditorGUI.GetPropertyHeight(element);
        return height;
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        arrayList.DoLayoutList();
        serializedObject.ApplyModifiedProperties();
    }
}

修改后如下图所示
在这里插入图片描述

示例二

高度计算放在PropertyDrawer的OnGUI中

自定义类

显示折叠箭头,数据元素内容显示为一行,Element修改为指定名称

using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(Test))]
public class TestDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        var spName = property.FindPropertyRelative("name");
        var spAge = property.FindPropertyRelative("age");

        var rect0 = position;
        rect0.height = EditorGUIUtility.singleLineHeight;

        var indentlevel = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 1;
      
        property.isExpanded = EditorGUI.Foldout(rect0, property.isExpanded, label);
      
        EditorGUI.indentLevel = indentlevel;

        if (property.isExpanded)
        {
            var rect1 = position;
            var rect2 = position;

            indentlevel = EditorGUI.indentLevel;
            var lableWidth = EditorGUIUtility.labelWidth;
            EditorGUI.indentLevel = 2;
            EditorGUIUtility.labelWidth = 60;

            rect1.width = position.width / 2;
            rect1.height = EditorGUIUtility.singleLineHeight;
            rect1.y += EditorGUIUtility.singleLineHeight;

            rect2.width = position.width / 2;
            rect2.height = EditorGUIUtility.singleLineHeight;

            rect2.x = position.width / 2 + 40;
            rect2.y = rect1.y;

            EditorGUI.PropertyField(rect1, spName, new GUIContent("名字"));
            EditorGUI.PropertyField(rect2, spAge, new GUIContent("年龄"));

            EditorGUI.indentLevel = indentlevel;
            EditorGUIUtility.labelWidth = lableWidth;
            //EditorGUI.DrawRect(rect1, Color.green);
            //EditorGUI.DrawRect(rect2, Color.gray);
        }
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        if (property.isExpanded)
            return EditorGUIUtility.singleLineHeight * 2;
        else
            return EditorGUIUtility.singleLineHeight;
    }
}

数据类

TestList修改为指定名称

using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(TestSO))]
public class TestSOEditor : Editor
{
    SerializedProperty sPTestList;
    ReorderableList arrayList;

    private void OnEnable()
    {
        sPTestList = serializedObject.FindProperty("testList");
        if (arrayList == null)
        {
            arrayList = new ReorderableList(serializedObject, sPTestList, true, true, true, true);
            //绘制Header
            arrayList.drawHeaderCallback += DrawHeader;
            //绘制数组元素
            arrayList.drawElementCallback += DrawElement;
            //绘制元素高度
            arrayList.elementHeightCallback += DrawHeight;

            void DrawHeader(Rect rect)
            {
                EditorGUI.LabelField(rect, "测试列表");
            }

            void DrawElement(Rect rect, int index, bool isActive, bool isFocused)
            {
            	//参数会传递给PropertyDrawer的OnGUI 
                EditorGUI.PropertyField(rect, sPTestList.GetArrayElementAtIndex(index), new GUIContent("元素 " + index));
            }

            float DrawHeight(int index)
            {
                return EditorGUI.GetPropertyHeight(sPTestList.GetArrayElementAtIndex(index));
            }
        }
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        arrayList.DoLayoutList();
        serializedObject.ApplyModifiedProperties();
    }
}

参考

看完后理解列表的高度如何计算

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/904319.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

聊聊Web3D 发展趋势

随着 Web 技术的不断演进&#xff0c;Web3D 正逐渐成为各行业数字化的重要方向。Web3D 是指在网页中展示 3D 内容的技术集合。近年来&#xff0c;由于 WebGL、WebGPU 等技术的发展&#xff0c;3D 内容已经能够直接在浏览器中渲染&#xff0c;为用户提供更加沉浸、互动的体验。以…

【AIGC】ChatGPT应用之道:如何打破『专家幻象』,提升AI协作质量

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;ChatGPT的实际能力用户对ChatGPT的常见误解超越误解&#xff0c;合理设定期望总结 &#x1f4af;超越“专家”幻想设定合理的期望总结 &#x1f4af;提升人工智能协作质量…

Web3的去中心化社交网络:区块链技术如何改变互动方式

随着互联网技术的不断进步&#xff0c;社交网络正在经历一场深刻的变革。Web3&#xff0c;作为新一代互联网技术的代表&#xff0c;正通过区块链和去中心化理念改变着我们与他人互动的方式。传统的社交网络通常由大型公司控制&#xff0c;用户数据的集中化管理和隐私问题备受关…

计算机网络:网络层 —— IPv4 协议的表示方法及其编址方法

文章目录 IPv4IPv4的表示方法IPv4的编址方法分类编址A类地址B类地址C类地址可指派的地址数量一般不使用的特殊IPv4地址 划分子网编址子网掩码默认子网掩码 无分类编址方法地址掩码斜线记法无分类域间路由选择 CIDR IPv4 IPv4&#xff08;Internet Protocol version 4&#xff…

Amcor 如何借助 Liquid UI 实现SAP PM可靠性

背景介绍 安姆科是塑料行业的全球领军企业&#xff0c;该企业认识到 SAP 工厂维护&#xff08;SAP PM&#xff09;对于确保高效的维护管理的重要性。 在诸如制造业等高度依赖机械设备的行业中&#xff0c;SAP PM是一种通过数据驱动决策来最大限度减少停机时间、降低间接成本、…

玩转Docker | 使用Docker部署捕鱼网页小游戏

玩转Docker | 使用Docker部署捕鱼网页小游戏 一、项目介绍项目简介项目预览二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署捕鱼网页小游戏下载镜像创建容器检查容器状态下载项目内容查看服务监听端口安全设置四、访问捕鱼网页小游戏五、总结一、项目介绍…

没有对象来和我手撕红黑树吧

1. 红黑树的介绍 红黑树也是一种自平衡的二叉搜索树&#xff0c;在每一个节点增加了一个存储位来表示节点的颜色&#xff0c;可以是红色也可以是黑色&#xff0c;通过约束颜色来维持树的平衡&#xff0c;具有以下的性质&#xff1a; 每个节点不是红色就是黑色根节点为黑色如果…

怎么实现电脑控制100台手机,苹果手机群控系统不用越狱实现新突破

今天来给大家介绍一款软件——手机群控。 什么是手机群控&#xff1f;就是将多台手机同时连接至一台电脑&#xff0c;集中控制管理。 对于苹果iOS免越狱中控&#xff0c;此前一直是个难题。 毕竟iOS系统封闭性极强&#xff0c;且苹果官方限制了USB的传输类型&#xff0c;只允…

【网络面试篇】TCP与UDP类

目录 一、综述 1. TCP与UDP的概念 2. 特点 3. 区别 4. 对应的使用场景 二、补充 1. 基础概念 &#xff08;1&#xff09;面向连接 &#xff08;2&#xff09;可靠的 &#xff08;3&#xff09;字节流 2. 相关问题 &#xff08;1&#xff09;TCP 和 UDP 可以同时绑定…

web自动化测试平台开发之核心执行器

web自动化测试平台开发之核心执行器 一、如何从自动化框架到核心执行器二、核心执行器框架逻辑梳理三、核心执行器利用命令驱动执行 一、如何从自动化框架到核心执行器 脚本:底层用了三个内容:pythonpytestselenium&#xff0c;线性脚本&#xff0c;只是单纯的把功能测试用例转…

AI自媒体变现路径大盘点!建议收藏!

当下的我做为一人公司或者超级个体为目标的创业模式&#xff0c;无论是在写作、图文和短视频输出方面&#xff0c;我都是运用了N个AI工具来提升我的生产力。 这种创业模式就是一个人N个AI的模式&#xff0c;我们可以通过AI工具做提效来赚取差价&#xff0c;以时间复利来累计财…

Boost电路双闭环控制MATLAB仿真

一、Boost电路电流内环控制MATLAB仿真模型 1.MATLAB仿真模型 1.1.仿真模型图 因为要使用电流内环控制&#xff0c;相比较于开环控制中直接给定MOS开关的占空比&#xff0c;这里通过把电路的平均电流和一电流基准值相比较来控制MOS开关的占空比&#xff0c;因此称为闭环控制。…

centos7 zabbix监控nginx的pv和uv和status_code

zabbix监控nginx的pv&#xff1a; pv)cat /var/log/nginx/access.log|awk {print $1}|wc -l;;zabbix-get验证&#xff1a; [rootbogon ~]# zabbix_get -s 192.168.253.231 -k pv_uv[pv] 100zabbix监控nginx的uv uv)cat /var/log/nginx/access.log|awk {print $1}|uniq -c | w…

分布式系统理论基础:Raft、Zab

目录 引言RaftZabPaxos、Raft、Zab再比较小结 该系列博文会告诉你什么是分布式系统&#xff0c;这对后端工程师来说是很重要的一门学问&#xff0c;我们会逐步了解分布式理论中的基本概念&#xff0c;常见算法、以及一些较为复杂的分布式原理&#xff0c;同时也需要进一步了解…

Ubuntu 20.04 安装 OpenCV 和 OpenCV_contrib 教程

Ubuntu 20.04 安装 OpenCV 和 OpenCV_contrib 教程 Ubuntu 20.04 安装 OpenCV 和 OpenCV_contrib 教程前言 OpenCV概述核心功能优势特点应用领域安装与使用 OpenCV_contrib概述核心功能具体模块 安装与使用一、准备工作二、下载OpenCV和OpenCV_contrib三、编译和安装OpenCV四、…

【鸿蒙HarmonyOS实战:通过华为应用市场上架测试版App实现HBuilder X打包的UniApp项目的app转hap教程(邀请码)方式教程详解】

鸿蒙HarmonyOS实战&#xff1a;通过华为应用市场上架测试版App实现HBuilder X打包的UniApp项目的app转hap教程&#xff08;邀请码&#xff09;方式详解 在使用uniapp打包的鸿蒙项目的过程中&#xff0c;由于生成的是app文件&#xff0c;而hdc传给鸿蒙HarmonyOS系统需要的是hap文…

HarmonyOS 5.0应用开发——应用打包HAP、HAR、HSP

【高心星出品】 目录 应用打包HAP、HAR、HSPModule类型HAPHAR创建HAR建立依赖HAR共享内容 HSP创建HSP建立依赖同上HSP共享内容同上 HAR VS HSP 应用打包HAP、HAR、HSP 一个应用通常会包含多种功能&#xff0c;将不同的功能特性按模块来划分和管理是一种良好的设计方式。在开发…

数据结构————map,set详解

今天带来map和set的详解&#xff0c;保证大家分清楚 一&#xff0c;概念 map和set是一种专门用来搜索的容器或数据结构 map能存储两个数据类型&#xff0c;我们称之为<key-value>模型 set只能存储一个数据类型&#xff0c;我们称之为纯<key>模型 它们的效率都非…

Vue.js(2): 组件与路由基础指南

这一路上可能会有艰辛、困难、疑惑、付出、泪水、失败&#xff0c;但是一定要享受这个过程&#xff0c;因为所有的失败都是为了下一刻的成功 文章目录 组件什么是组件组件化开发的好处组件底层是什么全局注册组件局部注册组件组件嵌套组件命名规则组件传值 SPAvue-router路由动…

[c++高阶]二叉搜索树深度剖析

1.前言 从二叉搜索树开始&#xff0c;后面慢慢学的AVL树&#xff0c;红黑树&#xff0c;map,set&#xff0c;哈希表等等都会慢慢的变得更难了&#xff0c;也更加难以理解了。希望大家能够坚持下去&#xff0c;只要坚持&#xff0c;就是胜利。 本章重点 着重讲解什么是二叉搜索…