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
相关产品推荐
相关产品推荐

