当前位置: 首页 > news >正文

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);    //绘制HeaderarrayList.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;elsereturn 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);//绘制HeaderarrayList.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();}
}

参考

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

相关文章:

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

了解 单行高度:EditorGUIUtility.singleLineHeight获取 PropertyField 控件所需的高度:EditorGUI.GetPropertyHeight属性是否在Inspector窗口展开&#xff1a;SerializedProperty.isExpanded可重新排序列表类&#xff1a;ReorderableList绘制纯色矩形&#xff1a;EditorGUI.Dr…...

ERC论文阅读(03)--SPCL论文阅读笔记(2024-10-29)

SPCL论文阅读笔记 论文中心思想 这篇论文是研究ERC任务的论文&#xff0c;作者提出了监督原型对比学习的方法用于ERC任务。 论文 EMNLP2022 paper “Supervised Prototypical Contrastive Learning for Emotion Recognition in Conversation” 现存问题 现存的使用监督对…...

Straightforward Layer-wise Pruning for More Efficient Visual Adaptation

对于模型中冗余的参数&#xff0c;一个常见的方法是通过结构化剪枝方法减少参数容量。例如&#xff0c;基于幅度值和基于梯度的剪枝方法。尽管这些方法在传统训练上通用性&#xff0c;本文关注的PETL迁移有两个不可避免的问题&#xff1a; 显著增加了模型存储负担。由于不同的…...

喜讯 | 创邻科技杭州电子科技大学联合实验室揭牌成立!

近日&#xff0c;杭州电子科技大学图书情报专业硕士行业导师聘任仪式暨杭电-创邻图技术与数字化联合实验室&#xff08;图书档案文物数字云联合研发中心&#xff09;揭牌仪式在杭州电子科技大学隆重举行。杭州电子科技大学原副校长吕金海、研究生院副院长潘建江&#xff0c;科研…...

海外媒体发稿:如何打造媒体发稿策略

新闻媒体的发稿推广策略对于提升品牌知名度、吸引流量以及增加收入非常重要。本文将介绍一套在21天内打造爆款新闻媒体发稿推广策略的方法。 第一天至第七天&#xff1a;明确目标和定位 在这个阶段&#xff0c;你需要明确你的目标和定位&#xff0c;以便为你的新闻媒体建立一个…...

PyTorch模型保存与加载

1.保存与加载的概念(序列化与反序列化) 模型训练完毕之后,肯定想要把它保存下来,供以后使用,不需要再次去训练。 那么在pytorch中如何把训练好的模型,保存,保存之后又如何加载呢? 这就用需要序列化与反序列化,序列化与反序列化的概念如下图所示: 因为在内…...

CH569开发前的测试

为了玩转准备Ch569的开发工作 &#xff0c;准备了如下硬件和软件&#xff1a; 硬件 1.官方的 Ch569 开发板&#xff0c;官方买到的是两块插接在一起的&#xff1b;除了HSPI接口那里的电阻&#xff0c;这两块可以说是一样的。也意味着两块板子的开发也需要烧录两次&#xff1b…...

MySQL中表的外连接和内连接

内连接和外连接 ​ 表的连接分为内连接和外连接&#xff0c;内连接就是将需要连接的表形成笛卡尔积筛选&#xff1b;外连接分为左外连接和右外连接&#xff0c;左外连接为左侧的表需要完全显示&#xff0c;右外连接为右侧的表现需要完全显示。 文章目录 内连接和外连接内连接外…...

Ubuntu 上安装 Redmine 5.1 指南

文章目录 官网安装文档&#xff1a;命令步骤相关介绍GemRubyRailsBundler 安装 Redmine更新系统包列表和软件包&#xff1a;安装必要的依赖&#xff1a;安装 Ruby&#xff1a;安装 bundler下载 Redmine 源代码&#xff1a;安装 MySQL配置 Redmine 的数据库配置文件&#xff1a;…...

从变量的角度理解 Hooks , 变得更简单了

从变量角度理解Hooks 在React的世界里&#xff0c;Hooks的引入为函数式组件带来了前所未有的灵活性和能力。它们让我们得以完全摆脱class式的写法&#xff0c;在函数式组件中完成生命周期管理、状态管理、逻辑复用等几乎全部组件开发工作。这次&#xff0c;我们就从变量的角度…...

LabVIEW Modbus通讯稳定性提升

在LabVIEW开发Modbus通讯程序时&#xff0c;通讯不稳定是一个常见问题&#xff0c;可能导致数据丢失、延迟或错误。为了确保通讯的可靠性&#xff0c;可以从多个角度进行优化&#xff0c;以下是一些有效的解决方案&#xff0c;结合实际案例进行分析。 1. 优化通讯参数设置 通讯…...

(8) cuda分析工具

文章目录 Nvidia GPU性能分析工具Nsight SystemNvidia GPU性能分析工具Nsight System Nvidia GPU性能分析工具Nsight System NVIDIA Nsight Systems是一个系统级的性能分析工具&#xff0c;用于分析和优化整个CUDA应用程序或系统的性能。它可以提供对应用程序整体性能的全面见…...

C语言 | Leetcode C语言题解之第517题超级洗衣机

题目&#xff1a; 题解&#xff1a; int findMinMoves(int* machines, int machinesSize){int sum0;for(int i0;i<machinesSize;i){summachines[i];}if(sum%machinesSize!0){return -1;}int psum/machinesSize;int ans0;int cur0;for(int i0;i<machinesSize;i){cur(mac…...

Java多线程编程基础

目录 编写第一个多线程程序 1. 方式一 : 继承Thread类, 重写run方法 2. 方式二: 实现Runnable接口, 重写run方法 3. 方式三: 使用Lambda表达式 [匿名内部类] [Lambda表达式] 在上个文章中, 我们了解了进程和线程的相关概念. 那么, 在Java中, 我们如何进行多线程编程呢? …...

刷代随有感(134):单调栈——下一个更大元素I(难点涉及哈希表与单调栈的结合)

单调栈处理的是下标&#xff01; 题干&#xff1a; 代码&#xff1a; class Solution { public:vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {stack<int>ddst;unordered_map<int,int>umap;vector<int…...

Linux云计算 |【第五阶段】CLOUD-DAY5

主要内容&#xff1a; 容器的镜像编排&#xff0c;commit简单镜像创建&#xff0c;Dockerfile制作服务镜像&#xff08;语法、创建镜像&#xff09;、创建复杂镜像&#xff08;Docker微服务架构、示例&#xff1a;NGINXPHP&#xff09;、私有仓库 一、简单镜像创建 1、自定义…...

被上传文件于后端的命名策略

上一篇博客我们了解了前端上传的文件资源应该存放在后端项目中的什么位置&#xff0c;那么随之而来的另一个问题——我们应该如何为上传的文件命名呢&#xff1f;往往直接采用原文件名并不稳妥&#xff0c;会导致命名冲突、文件冲突、数据库管理冲突等多种问题&#xff0c;下面…...

哈希表 算法专题

哈希表简介 是什么 存储数据的容器有啥用? "快速"查找某个元素什么时候用哈希表 频繁地查找某个数(有序用二分)怎么用哈希表 容器用数组模拟 字符串中的字符 范围比较小的数 一. 两数之和 两数之和 class Solution {public int[] twoSum(int[] nums, int targe…...

unity3d————[HideInInspector]

在Unity3D中&#xff0c;[HideInInspector]是一个属性修饰符&#xff0c;它的主要作用是在Unity的Inspector窗口中隐藏变量或属性。以下是关于[HideInInspector]的详细解释和作用&#xff1a; 作用 隐藏变量或属性&#xff1a;当你在脚本中使用[HideInInspector]修饰符时&…...

Soanrquber集成Gitlab 之 导入Gitlab项目

集成Gitlab 之 导入Gitlab项目 说明&#xff1a; Sonarquber里面的项目&#xff0c;顺便设置&#xff0c;只要在集成CI的时候&#xff0c;使用这个项目的项目标识即可。 当然项目名称一一对应是最好的了&#xff0c;所以这里讲导入Gitlab的项目&#xff0c;项目名称一一对应&…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

数据结构:递归的种类(Types of Recursion)

目录 尾递归&#xff08;Tail Recursion&#xff09; 什么是 Loop&#xff08;循环&#xff09;&#xff1f; 复杂度分析 头递归&#xff08;Head Recursion&#xff09; 树形递归&#xff08;Tree Recursion&#xff09; 线性递归&#xff08;Linear Recursion&#xff09;…...

人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型

在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重&#xff0c;适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解&#xff0c;并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...

ArcPy扩展模块的使用(3)

管理工程项目 arcpy.mp模块允许用户管理布局、地图、报表、文件夹连接、视图等工程项目。例如&#xff0c;可以更新、修复或替换图层数据源&#xff0c;修改图层的符号系统&#xff0c;甚至自动在线执行共享要托管在组织中的工程项。 以下代码展示了如何更新图层的数据源&…...

MySQL体系架构解析(三):MySQL目录与启动配置全解析

MySQL中的目录和文件 bin目录 在 MySQL 的安装目录下有一个特别重要的 bin 目录&#xff0c;这个目录下存放着许多可执行文件。与其他系统的可执行文件类似&#xff0c;这些可执行文件都是与服务器和客户端程序相关的。 启动MySQL服务器程序 在 UNIX 系统中&#xff0c;用…...

【Ftrace 专栏】Ftrace 参考博文

ftrace、perf、bcc、bpftrace、ply、simple_perf的使用Ftrace 基本用法Linux 利用 ftrace 分析内核调用如何利用ftrace精确跟踪特定进程调度信息使用 ftrace 进行追踪延迟Linux-培训笔记-ftracehttps://www.kernel.org/doc/html/v4.18/trace/events.htmlhttps://blog.csdn.net/…...