Reputation: 85
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);
}
}
Upvotes: 3
Views: 1170
Reputation: 11
The real answer turns out to be that you need a getter and setter for the member variable, and it must match the name field.
UxmlStringAttributeDescription meow = new UxmlStringAttributeDescription { name = "my-example-value", defaultValue = "TestElementString" };
with a name like that you need a getter and setter excactly like this:
private string MyExampleValue { get; set; }
The source material: https://forum.unity.com/threads/uxmltraits-and-custom-attributes-resetting-in-inspector.966215/
Upvotes: 1
Reputation: 416
This could have changed throughout the updates. Just reporting in that I am using Unity 2022.3.10f1 and in my tests the only important thing is that the variable name of the VisualElement must match with the name
property of the UxmlAttributeDescription
So this should work out fine:
enter code here
public class TestElement : VisualElement
{
public string myCustomValue { get; set; }
public new class UxmlFactory : UxmlFactory<TestElement,UxmlTraits> {}
public new class UxmlTraits : VisualElement.UxmlTraits
{
UxmlStringAttributeDescription thisNameDoesNotMatter =
new UxmlStringAttributeDescription
{
name = "my-custom-value",
defaultValue = "TestElementString"
};
public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
{
base.Init(ve, bag, cc);
var ate = ve as TestElement;
ate.myCustomValue = thisNameDoesNotMatter.GetValueFromBag(bag, cc);
}
}
}
Upvotes: 0
Reputation: 1637
AttributeDescription
's name should end with Attr
suffix{get;set;}
property must exist & named the same but without that Attr
suffixSerialization 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);
}
}
}
Upvotes: 4