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

Unity自定义VisualElement:UxmlTraits子元素不加载,UI Builder状态重置

问题:自定义VisualElement在UI Builder保存后状态重置

我尝试创建一个自定义VisualElement,通过在Inspector中设置枚举属性来显示/隐藏单个子元素,但在UI Builder中使用该带有两个子元素的UI元素并保存后,所有状态都会重置。请问我哪里出错了?

public class VpWidgetMainSidebarVisualElement : VisualElement
{
    private SidebarContentEnum _sidebarContent;
    public SidebarContentEnum SidebarContent
    {
        get => _sidebarContent;
        set => SetSidebarContent(value);
    }

    public VpWidgetMainSidebarVisualElement()
    {
        UpdateSidebarContentVisibility();
    }

    private void SetSidebarContent(SidebarContentEnum value)
    {
        _sidebarContent = value;
        UpdateSidebarContentVisibility();
    }
    private void UpdateSidebarContentVisibility()
    {
        if (this.childCount > 0)
        {
            var i = 0;
            foreach (var ve in this.Children())
            {
                ve.style.display = new StyleEnum<DisplayStyle>(i == (int)_sidebarContent ? DisplayStyle.Flex : DisplayStyle.None);
                ve.MarkDirtyRepaint();
                i++;
            }
        }
    }

    [Preserve]
    public new class UxmlFactory : UxmlFactory<VpWidgetMainSidebarVisualElement, UxmlTraits>
    {
    }

    [Preserve]
    public new class UxmlTraits : VisualElement.UxmlTraits
    {
        private UxmlEnumAttributeDescription<SidebarContentEnum> _sidebarContent = new() { name = "sidebar-content", defaultValue = SidebarContentEnum.BrowsProduct };
        public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
        {
            get
            {
                yield break;
            }
        }

        public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
        {
            base.Init(ve, bag, cc);
            var widget = (VpWidgetMainSidebarVisualElement)ve;
            widget.SetSidebarContent(_sidebarContent.GetValueFromBag(bag, cc));
        }
    }

    public enum SidebarContentEnum
    {
        BrowsProduct,
        ProductDetails
    }
}

问题根源

代码中UxmlTraits类的uxmlChildElementsDescription返回yield break,这会告知UI Builder该自定义元素不支持添加子元素。因此你在UI Builder中添加的子元素不会被序列化到UXML文件,保存后重新加载时这些子元素会丢失,最终导致状态重置。

修复方案

修改uxmlChildElementsDescription,让它继承父类的子元素描述,这样UI Builder就能正确识别并保存子元素:

[Preserve]
public new class UxmlTraits : VisualElement.UxmlTraits
{
    private UxmlEnumAttributeDescription<SidebarContentEnum> _sidebarContent = new() { name = "sidebar-content", defaultValue = SidebarContentEnum.BrowsProduct };
    
    // 替换原有的yield break,继承父类的子元素描述
    public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
    {
        get => base.uxmlChildElementsDescription;
    }

    public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
    {
        base.Init(ve, bag, cc);
        var widget = (VpWidgetMainSidebarVisualElement)ve;
        widget.SetSidebarContent(_sidebarContent.GetValueFromBag(bag, cc));
    }
}

内容的提问来源于stack exchange,提问作者Ehsan Zargar Ershadi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 23:05:24