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

如何让自定义Property Drawer字段与Unity内置字段对齐?

解决UI Toolkit自定义Couple属性Drawer与内置字段对齐问题

我有一个通用Couple类,可像元组一样序列化两个泛型属性。此前用IMGUI实现的自定义Property Drawer能在Inspector中将其放在一行,标签与输入字段均与Unity内置属性对齐。现在迁移到UI Toolkit后功能已基本实现,但无法让字段始终与内置字段对齐。

当前进展

  • 查阅Unity文档得知unity-base-field__aligned类负责拉伸标签宽度以实现对齐,尝试复刻元素树结构并应用该类,但推测它仅对BaseField<T>的子类生效。且该类似乎通过脚本计算宽度并内联应用,我更倾向于使用USS样式和类解决问题。
  • 使用unity-base-field__label类为标签设置最小宽度,在Inspector面板足够小时能达到预期效果,但面板宽度变大后对齐失效。

代码实现

UI Toolkit版本(存在对齐问题)

using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

[CustomPropertyDrawer(typeof(Couple<,>))]
public class CoupleEditor : PropertyDrawer {

    public override VisualElement CreatePropertyGUI(SerializedProperty property) {
        // 创建属性容器
        var container = new VisualElement();
        container.style.flexDirection = FlexDirection.Row;

        // 创建标签
        var label = new Label(property.displayName);
        label.AddToClassList("unity-base-field__label"); // 设置最小宽度为120px

        // 创建输入容器
        var input = new VisualElement();
        input.style.flexDirection = FlexDirection.Row;
        input.style.flexGrow = 1f;

        // 创建属性字段
        var item1 = new PropertyField(property.FindPropertyRelative(nameof(Couple<int, int>.Item1)), "");
        var item2 = new PropertyField(property.FindPropertyRelative(nameof(Couple<int, int>.Item2)), "");
        item1.style.flexGrow = 1f;
        item2.style.flexGrow = 1f;

        // 添加元素到容器
        container.Add(label);
        input.Add(item1);
        input.Add(item2);
        container.Add(input);

        return container;
    }

参考:可正常对齐的IMGUI版本

// 可正常工作的IMGUI实现
    public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label) {
        // 对父属性使用BeginProperty/EndProperty,确保预制件覆盖逻辑对整个属性生效
        _ = EditorGUI.BeginProperty(rect, label, property);

        // 绘制标签
        rect = EditorGUI.PrefixLabel(rect, GUIUtility.GetControlID(FocusType.Passive), label);

        // 禁用内联字段的缩进
        var indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        // 计算字段矩形
        var fieldGap = 8f;
        var fieldWidth = (rect.width - fieldGap) / 2f;
        var rect1 = new Rect(rect.x, rect.y, fieldWidth, rect.height);
        var rect2 = new Rect(rect.x + fieldWidth + fieldGap, rect.y, fieldWidth, rect.height);

        // 绘制字段 - 传入GUIContent.none让字段不显示自身标签
        _ = EditorGUI.PropertyField(rect1, property.FindPropertyRelative(nameof(Couple<int, int>.Item1)), GUIContent.none);
        _ = EditorGUI.PropertyField(rect2, property.FindPropertyRelative(nameof(Couple<int, int>.Item2)), GUIContent.none);

        // 恢复缩进
        EditorGUI.indentLevel = indent;

        EditorGUI.EndProperty();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:47:34