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

Unity CustomPropertyDrawer异常:数组元素修改错位问题

Unity自定义LabeledArrayAttribute数组元素修改偏移问题修复

我实现了一个LabeledArrayAttribute,用来替换Unity Inspector中数组默认的“Element 0”“Element 1”这类标签,支持直接传入字符串数组或枚举类型生成自定义元素名称。但使用时发现异常:

  • 当数组元素数量对应枚举长度(20个)时,修改第一个元素,变更会显示在第二个元素上,以此类推
  • 仅1个元素时,修改操作无可见效果
  • 第21个及以后的元素功能正常

原实现代码

属性定义与测试类

public class LabeledArrayAttribute : PropertyAttribute {
    public readonly string[] names;
    public LabeledArrayAttribute(string[] names) { this.names = names; }
    public LabeledArrayAttribute(Type enumType) { names = Enum.GetNames(enumType); }
}

public class ColorManager : MonoBehaviour
{
    public enum FollowColor {
        Accent,
        Background,
        Border,
        Button,
        Disabled,
        Error,
        Foreground,
        Header,
        Highlight,
        Hover,
        Info,
        Link,
        Primary,
        Secondary,
        Selected,
        Success,
        Tab,
        Tetriary,
        Text,
        Warning
    }

    [LabeledArray(typeof(FollowColor))]
    public Color[] Colors = new Color[20];
}

自定义PropertyDrawer

[CustomPropertyDrawer(typeof(LabeledArrayAttribute))]
public class LabeledArrayDrawer : PropertyDrawer {
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
        return EditorGUI.GetPropertyHeight(property, label, true);
    }

    public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label) {
        try {
            EditorGUI.BeginProperty(rect, label, property);

            var path = property.propertyPath;
            int pos = int.Parse(path.Split('[').LastOrDefault().TrimEnd(']'));
            EditorGUI.PropertyField(rect, property, new GUIContent(((LabeledArrayAttribute) attribute).names[pos]), true);

            EditorGUI.EndProperty();
        } catch {
            EditorGUI.PropertyField(rect, property, label, true);
        }
    }
}

问题原因

通过字符串分割propertyPath获取数组元素索引的方式不可靠,Unity内部序列化路径的格式可能存在变化,导致解析出的索引与实际元素索引偏移,进而出现修改操作错位的情况。

修复方案

使用Unity官方提供的SerializedProperty.GetArrayElementIndex()方法直接获取元素在数组中的索引,该方法能准确返回当前元素的数组索引,避免字符串解析的误差。同时增加索引范围判断,避免数组越界异常。

修改后的PropertyDrawer代码

[CustomPropertyDrawer(typeof(LabeledArrayAttribute))]
public class LabeledArrayDrawer : PropertyDrawer {
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
        return EditorGUI.GetPropertyHeight(property, label, true);
    }

    public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label) {
        try {
            EditorGUI.BeginProperty(rect, label, property);

            // 使用官方方法获取数组元素索引,替代字符串分割
            int pos = property.GetArrayElementIndex();
            var labeledAttribute = (LabeledArrayAttribute)attribute;
            
            // 确保索引在有效范围内,避免越界
            if (pos >= 0 && pos < labeledAttribute.names.Length)
            {
                EditorGUI.PropertyField(rect, property, new GUIContent(labeledAttribute.names[pos]), true);
            }
            else
            {
                // 超出自定义名称范围时,使用默认标签
                EditorGUI.PropertyField(rect, property, label, true);
            }

            EditorGUI.EndProperty();
        } catch {
            EditorGUI.PropertyField(rect, property, label, true);
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 18:57:03