Skip to main content
added 68 characters in body
Source Link
Charly
  • 742
  • 3
  • 11
Solution

You can use a VisualTreeAsset. It's a serialized Visual Element Tree. Instantiate it and child the resulting root node to the UIdocument of your scene. Then you can query for elements and change values procedurally.

class TestMono : MonoBehaviour{
        //TODO: assign these members in the inspector
        [SerializeField] VisualTreeAsset myTreeAssetMember;
        [SerializeField] UIDocument UIDocument;

        private void Start()
        {
            TemplateContainer myUI = myTreeAssetMember.Instantiate();
            
            //an example of querying for the root element of a button template with the id "submit"
            Button button = myUI.Q<Button>("submit");
            if (button != null)
             button.clickable = new Clickable(() => Debug.Log("Stub submit button clicked."));
            else
                Debug.LogWarning($"Could not find \"submit\" button.");
            
            //child the template to the UIDocument so it will be rendered and updated
            UIDocument.rootVisualElement.Add(myUI);
        }
    }

enter image description here

On Asset Loading Concerns

I want to do that, but the code to load such a VisualTreeAsset that i found previously only work in the editor mode :( AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/menu.uxml"); EditorGUIUtility.Load("Assets/menu.uxml") as VisualTreeAsset; if you know another way that doesn't require the editor, I'm all ears

Because a VisualTreeAsset is serializable you can use what's called a "direct reference" in Unity:

  • Prefix a VisualTreeAsset member with [SerializeField]
  • Assign the field in the inspector.

Now Unity will automatically include it, and any other directly referenced assets, in the build. It will automatically be loaded into memory with everything else in that scene. You won't have to use the AssetDatabase, or any other APIs only available when the UNITY_EDITORUNITY_EDITOR is present. If for whatever reason you can't use a direct reference but still need a solution which works on device you can look into Unity's Resource API for something simple or Addressables for a more robust and scalable solution.

Solution

You can use a VisualTreeAsset. It's a serialized Visual Element Tree. Instantiate it and child the resulting root node to the UIdocument of your scene. Then you can query for elements and change values procedurally.

class TestMono : MonoBehaviour{
        //TODO: assign these members in the inspector
        [SerializeField] VisualTreeAsset myTreeAssetMember;
        [SerializeField] UIDocument UIDocument;

        private void Start()
        {
            TemplateContainer myUI = myTreeAssetMember.Instantiate();
            
            //an example of querying for the root element of a button template with the id "submit"
            Button button = myUI.Q<Button>("submit");
            if (button != null)
             button.clickable = new Clickable(() => Debug.Log("Stub submit button clicked."));
            else
                Debug.LogWarning($"Could not find \"submit\" button.");
            
            //child the template to the UIDocument so it will be rendered and updated
            UIDocument.rootVisualElement.Add(myUI);
        }
    }

enter image description here

On Asset Loading Concerns

I want to do that, but the code to load such a VisualTreeAsset that i found previously only work in the editor mode :( AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/menu.uxml"); EditorGUIUtility.Load("Assets/menu.uxml") as VisualTreeAsset; if you know another way that doesn't require the editor, I'm all ears

Because a VisualTreeAsset is serializable you can use what's called a "direct reference" in Unity:

  • Prefix a VisualTreeAsset member with [SerializeField]
  • Assign the field in the inspector.

Now Unity will automatically include it, and any other directly referenced assets, in the build. You won't have to use the AssetDatabase, or any other APIs only available when the UNITY_EDITOR is present. If for whatever reason you can't use a direct reference but still need a solution which works on device you can look into Unity's Resource API for something simple or Addressables for a more robust and scalable solution.

Solution

You can use a VisualTreeAsset. It's a serialized Visual Element Tree. Instantiate it and child the resulting root node to the UIdocument of your scene. Then you can query for elements and change values procedurally.

class TestMono : MonoBehaviour{
        //TODO: assign these members in the inspector
        [SerializeField] VisualTreeAsset myTreeAssetMember;
        [SerializeField] UIDocument UIDocument;

        private void Start()
        {
            TemplateContainer myUI = myTreeAssetMember.Instantiate();
            
            //an example of querying for the root element of a button template with the id "submit"
            Button button = myUI.Q<Button>("submit");
            if (button != null)
             button.clickable = new Clickable(() => Debug.Log("Stub submit button clicked."));
            else
                Debug.LogWarning($"Could not find \"submit\" button.");
            
            //child the template to the UIDocument so it will be rendered and updated
            UIDocument.rootVisualElement.Add(myUI);
        }
    }

enter image description here

On Asset Loading Concerns

I want to do that, but the code to load such a VisualTreeAsset that i found previously only work in the editor mode :( AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/menu.uxml"); EditorGUIUtility.Load("Assets/menu.uxml") as VisualTreeAsset; if you know another way that doesn't require the editor, I'm all ears

Because a VisualTreeAsset is serializable you can use what's called a "direct reference" in Unity:

  • Prefix a VisualTreeAsset member with [SerializeField]
  • Assign the field in the inspector.

Now Unity will include it, and any other directly referenced assets, in the build. It will automatically be loaded into memory with everything else in that scene. You won't have to use the AssetDatabase, or any other APIs only available when the UNITY_EDITOR is present. If for whatever reason you can't use a direct reference but still need a solution which works on device you can look into Unity's Resource API for something simple or Addressables for a more robust and scalable solution.

Source Link
Charly
  • 742
  • 3
  • 11

Solution

You can use a VisualTreeAsset. It's a serialized Visual Element Tree. Instantiate it and child the resulting root node to the UIdocument of your scene. Then you can query for elements and change values procedurally.

class TestMono : MonoBehaviour{
        //TODO: assign these members in the inspector
        [SerializeField] VisualTreeAsset myTreeAssetMember;
        [SerializeField] UIDocument UIDocument;

        private void Start()
        {
            TemplateContainer myUI = myTreeAssetMember.Instantiate();
            
            //an example of querying for the root element of a button template with the id "submit"
            Button button = myUI.Q<Button>("submit");
            if (button != null)
             button.clickable = new Clickable(() => Debug.Log("Stub submit button clicked."));
            else
                Debug.LogWarning($"Could not find \"submit\" button.");
            
            //child the template to the UIDocument so it will be rendered and updated
            UIDocument.rootVisualElement.Add(myUI);
        }
    }

enter image description here

On Asset Loading Concerns

I want to do that, but the code to load such a VisualTreeAsset that i found previously only work in the editor mode :( AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/menu.uxml"); EditorGUIUtility.Load("Assets/menu.uxml") as VisualTreeAsset; if you know another way that doesn't require the editor, I'm all ears

Because a VisualTreeAsset is serializable you can use what's called a "direct reference" in Unity:

  • Prefix a VisualTreeAsset member with [SerializeField]
  • Assign the field in the inspector.

Now Unity will automatically include it, and any other directly referenced assets, in the build. You won't have to use the AssetDatabase, or any other APIs only available when the UNITY_EDITOR is present. If for whatever reason you can't use a direct reference but still need a solution which works on device you can look into Unity's Resource API for something simple or Addressables for a more robust and scalable solution.