In this lesson, you will learn how to bridge the gap between your game’s logic and your UI Toolkit interface by querying the visual tree to update elements in real-time.
The Visual Tree as a Bridge
In previous lessons, you designed your UI using the UI Builder. However, UI elements like Labels or Images are static by default. To make them dynamic—such as updating a player's health bar or displaying a score—you must programmatically "find" these elements within the UIDocument and inject new data into them.
Querying the Visual Tree
Think of your UI as a hierarchy of objects. To interact with one, you first need to reference the root of your UI document, then "query" it using the element’s name or type. Once you have a reference to the element, you can modify its properties directly via C#.
Here is how you update a label at runtime:
using UnityEngine;
using UnityEngine.UIElements;
public class ScoreUI : MonoBehaviour
{
private Label scoreLabel;
void OnEnable()
{
// 1. Get the root of the UI document
var root = GetComponent<UIDocument>().rootVisualElement;
// 2. Query the tree for an element named "ScoreLabel"
scoreLabel = root.Q<Label>("ScoreLabel");
}
public void UpdateScore(int newScore)
{
// 3. Inject dynamic data into the text property
if (scoreLabel != null)
{
scoreLabel.text = $"Score: {newScore}";
}
}
}
Why Querying Matters
By using root.Q<T>("Name"), you decouple your script from the specific structure of the visual tree. You don’t need to drag and drop references in the Inspector if you know the name of your UI element. This approach allows your UI to remain flexible; even if you restructure your layout in the UI Builder, your script will still find the target element as long as the name remains consistent.
Remember to perform your queries inside OnEnable or Start, as the visual tree is built when the UIDocument component is initialized.
Key Takeaway: Use the rootVisualElement.Q<T>("Name") method to grab references to UI components and update their properties through C# whenever your game state changes.