Search code examples
c#unity-game-engineui-toolkit

Unity UxmlAttributeDescription not setting values (resetting values)


I'm using the UI Builder for my UI and I'm creating some custom controls. I've already managed to make a custom control which works perfectly fine. But the second one has some problems I can't understand.

The problem: I'm able to put my custom control into the UI Builder. From the start there is no default value in the "status" attribute, it just blank. When I manually input a value and click away, the "status" value is reset to blank. In the console I'm getting the message "null" from the constructor, meaning the value I input was not set.

Additional information: The problem first occurred when I used the class UxmlIntAttributeDescription. I had a class with an UxmlStringAttributeDescription and an UxmlIntAttributeDescription. I was able to set the string attribute, but not the int attribute. I kept simplifying my code so I can post this question and then even the string attribute broke. I really don't know where I screwed up, hopefully someone can help me with this one.

Here is my code. Its mostly copied from https://docs.unity3d.com/Manual/UIE-UXML.html.

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

public class TestElement : VisualElement {
    public new class UxmlFactory : UxmlFactory<TestElement, UxmlTraits> { }

    public new class UxmlTraits : VisualElement.UxmlTraits {

        UxmlStringAttributeDescription m_status = new UxmlStringAttributeDescription { name = "status", defaultValue = "TestElementString" };
      
        public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription {
            get { yield break; }
        }
        
        public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc) {
            base.Init(ve, bag, cc);
            var ate = ve as TestElement;

            ate._status = m_status.GetValueFromBag(bag, cc);
        }
    }

    private string _status;
    
    public TestElement() {
        Debug.Log(_status);
    }
}

Solution


    • AttributeDescription's name should end with Attr suffix
    • corresponding public {get;set;} property must exist & named the same but without that Attr suffix

    Serialization system won't work with this element otherwise.

    public class TestElement : VisualElement
    {
        public string status { get; set; }
        public new class UxmlFactory : UxmlFactory<TestElement,UxmlTraits> {}
        public new class UxmlTraits : VisualElement.UxmlTraits
        {
            UxmlStringAttributeDescription statusAttr = new UxmlStringAttributeDescription { name = "status", defaultValue = "TestElementString" };
            public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
            {
                base.Init(ve, bag, cc);
                var ate = ve as TestElement;
    
                ate.status = statusAttr.GetValueFromBag(bag, cc);
            }
        }
    }