You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity自定义Enum索引数组PropertyDrawer展开类元素时UI重叠

问题描述

在Unity编辑器中实现了以枚举值作为数组元素索引显示名称的自定义PropertyDrawer,但Inspector面板展开数组时,数组元素属性直接绘制到数组下方的其他UI控件区域,没有为元素完整内容预留显示高度,导致展开的数组UI和下方脚本组件重叠,重叠效果如下:
展开数组与下方脚本重叠效果

移除枚举索引自定义绘制逻辑后数组可正常展开。测试验证该自定义绘制逻辑在int、string、float等基础值类型数组上可正常运行,仅在处理包含多个属性的自定义类、结构体数组时触发异常。旧版本Unity中曾遇到嵌套数组同类问题,升级版本即可修复,但当前使用最新正式版Unity,判断问题根源在自定义PropertyDrawer的代码实现中。


复现代码

1. 自定义特性定义

using UnityEngine;
public class EnumNamedArrayAttribute : PropertyAttribute
{
    public string[] names;
    public EnumNamedArrayAttribute(System.Type names_enum_type)
    {
        this.names = System.Enum.GetNames(names_enum_type);
    }
}

2. 自定义属性绘制器实现

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
[CustomPropertyDrawer(typeof(EnumNamedArrayAttribute))]
public class DrawerEnumNamedArray : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EnumNamedArrayAttribute enumNames = attribute as EnumNamedArrayAttribute;
        //propertyPath返回格式类似component_hp_max.Array.data[4]
        //从路径中提取索引
        int index = System.Convert.ToInt32(property.propertyPath.Substring(property.propertyPath.IndexOf("[")).Replace("[", "").Replace("]", ""));
        //修改显示标签
        label.text = enumNames.names[index];
        //绘制属性字段
        EditorGUI.PropertyField(position, property, label, true);
    }
}

3. 数组字段声明

[EnumNamedArray(typeof(Spells))]
public SpellBlueprint[] spellBlueprints;

public enum Spells
{
    fireball,lightningbolt,frostbolt
}

4. 数组元素类定义

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class SpellBlueprint
{
    public float speed = 20f;
    public float damage = 15f;

    public bool AOE_enabled = false;

    public GameObject SpellPrefab;
}

补充说明

该枚举命名数组绘制器对int、string、float等基础类型数组完全生效,仅处理包含多个属性的自定义类或结构体时出现布局异常。


问题原因

自定义绘制器没有重写GetPropertyHeight方法,Unity默认只返回单行属性的高度。基础类型数组元素都是单行高度,所以不会出现重叠;自定义类/结构体展开后是多行内容,高度计算错误就会导致UI重叠。

修复方案

在自定义PropertyDrawer中重写GetPropertyHeight方法,返回属性实际需要的绘制高度,修改后的绘制器代码如下:

using UnityEngine;
using UnityEditor;

[CustomPropertyDrawer(typeof(EnumNamedArrayAttribute))]
public class DrawerEnumNamedArray : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EnumNamedArrayAttribute enumNames = attribute as EnumNamedArrayAttribute;
        int index = System.Convert.ToInt32(property.propertyPath.Substring(property.propertyPath.IndexOf("[")).Replace("[", "").Replace("]", ""));
        label.text = enumNames.names[index];
        EditorGUI.PropertyField(position, property, label, true);
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        // 自动计算包含子属性的完整高度,第三个参数传true表示包含展开的子元素
        return EditorGUI.GetPropertyHeight(property, label, true);
    }
}

重写后Unity会正确获取数组元素展开后的总高度,自动为元素预留足够显示空间,不会再和下方UI重叠。

内容的提问来源于stack exchange,提问作者Insomnia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:33:21