Hello! Welcome back to the project.
In our last lesson, we put the final piece into our core character data model in Rust by defining the AgeStage enum. With the Character and Personality structs also complete, we now have a solid blueprint in our Rust backend for what a character is.
Today, we're shifting our focus back to the Unity frontend. Our goal is to create the user interface that will allow players to bring their characters to life. This lesson directly addresses the learning outcome: Build a character creator UI in Unity with inputs for name, age, personality sliders, and trait selection.
We'll be using Unity's modern UI Toolkit, which is a powerful, data-oriented system that neatly separates a UI's structure, styling, and logic. This aligns perfectly with our project's architecture and is a valuable skill for modern Unity development.
Let's get started.
1. Understanding the UI Toolkit
If you've used Unity's legacy UI system (Canvas, GameObjects, etc.), UI Toolkit might feel a bit different. It's modeled after web technologies and breaks a UI down into three parts:
- UXML (.uxml): An XML-based language that defines the structure and layout of the UI. This is similar to HTML.
- USS (.uss): A stylesheet language, similar to CSS, that controls the appearance (colors, fonts, spacing) of the UI elements.
- C# Scripts: These provide the functionality, handling user input and manipulating the UI elements.
This separation makes UIs more modular, maintainable, and easier to style. To get a quick overview of these concepts, let's watch the beginning of a helpful video.
Build Stunning UI Faster with Unity UI Toolkit (Unity 6).
This video from DebugDevin gives an excellent primer on the core concepts of the UI Toolkit and how to get started.
Watch from 00:21 to 02:28. This will introduce you to UXML, USS, and C#, and show you how to create your first UI Document and open the UI Builder.
Following the video's guidance, go ahead and create a new UI Document in your Unity project. I suggest creating a UI folder to keep things organized. Name the new file CharacterCreator.uxml. Double-click it to open the UI Builder window.
2. Designing the Layout with Flexbox
With the UI Builder open, our next task is to lay out the structure of our character creator. We need fields for all the data we defined in Rust.
UI Toolkit uses a powerful layout system called Flexbox to arrange elements. If you've done any web development, this will be familiar. The key is to understand how parent containers arrange their children along a main axis (either a row or a column).
Build Stunning UI Faster with Unity UI Toolkit (Unity 6).
The same video provides a clear and visual explanation of how Flexbox works within the UI Toolkit.
Watch from 02:28 to 07:18. Pay close attention to the concepts of main axis vs. cross axis, and the flex-direction, grow, and alignment properties. This is fundamental to creating responsive layouts.
Now, let's apply this. We'll create a vertical layout for our form. In the UI Builder's Hierarchy panel, start by dragging elements from the Library panel to create the following structure:
- A root
VisualElement: This will be our main container. By default, itsflex-directioniscolumn, which is what we want. - A
TextField: For the character's name. - A
DropdownField: For selecting the age stage. - Six
Sliderelements: For the HEXACO personality dimensions. - A few
Toggleelements: For selecting traits. - A
Button: To create the character.
For now, just drag these elements into the hierarchy. Don't worry about their appearance yet. Here's a visual example of what a finished character creator might look like in-game:

3. Configuring the UI Elements
Now let's configure each element in the Inspector panel within the UI Builder.
Name Field (TextField)
- Give it a
namein the Inspector, likecharacter-name. This is crucial for accessing it from our C# script later. - Set its
labelto "Name".
Age Stage (DropdownField)
- Set its
nametoage-stage-dropdown. - Set its
labelto "Age Stage". - In the Inspector, find the "Choices" list and add our four age stages:
Child,Teen,Adult, andElder.
Personality Sliders (Slider)
For each of the six sliders:
- Set its
labelto one of the HEXACO dimensions: Honesty-Humility, Emotionality, Extraversion, Agreeableness, Conscientiousness, Openness to Experience. - Set its
nameaccordingly (e.g.,honesty-slider). - Set the
low-valueto0andhigh-valueto1. This will make the slider output a float between 0.0 and 1.0, matching our RustPersonalitystruct.
You can find more details on configuring sliders in the Unity documentation.
The official Unity Manual provides detailed information on the Slider component for UI Toolkit, including all its properties.
Briefly read the introduction to understand the Slider's purpose. Then, scroll down to the 'Inherited UXML attributes' table. This is a great reference for properties like low-value, high-value, and label that you are using.
Traits (Toggle)
- Create three or four
Toggleelements. - Give each one a
labelfor a sample trait, like "Creative", "Ambitious", or "Bookworm". - Give each a unique
name(e.g.,creative-trait-toggle).
Create Button (Button)
- Set its
nametocreate-character-button. - Set its
textto "Create Character".
4. Styling with USS
With the structure in place, let's add some basic styling to make it look less plain. We'll do this using a USS stylesheet.
Build Stunning UI Faster with Unity UI Toolkit (Unity 6).
Let's return to the video guide to see how to create and apply USS stylesheets.
Watch from 10:34 to 14:48. This section demonstrates how to create a stylesheet, link it to your UXML, and apply styles using type, name (#), and class (.) selectors.
- In the UI Builder's StyleSheets panel, create a new stylesheet and save it as
CharacterCreator.uss. - Now you can add style rules. For example, to give your form some breathing room, you could select the root
VisualElementand add some padding in the Inspector. This will automatically create a new style rule in your USS file. - Try adding some styles yourself:
- Give the
create-character-buttona background color. - Add some margin below each element to space them out.
- Increase the font size for the labels.
- Give the
Experiment with the properties in the Inspector. This is the fastest way to learn what's possible with USS.
5. Hooking Up Logic with C#
Our UI looks good, but it doesn't do anything yet. The final step is to write a C# script to read the player's input when they click the "Create Character" button.
Build Stunning UI Faster with Unity UI Toolkit (Unity 6).
The final segment of the video shows how to access UI elements from a C# script and register event callbacks, like a button click.
Watch from 14:48 to 17:54. Focus on how a script gets a reference to the UIDocument, uses root.Q<ElementName>("element-name") to find specific elements, and uses RegisterCallback<ClickEvent>() to handle button presses.
Now, let's apply this to our scene.
- In your main Unity scene, create an empty GameObject and name it
UI Controller. - Add the
UI Documentcomponent to it. In theSource Assetfield, assign yourCharacterCreator.uxmlfile. You should now see your UI in the Game view. - Create a new C# script named
CharacterCreatorControllerand add it to theUI ControllerGameObject. - Open the script and add the following code:
using UnityEngine;
using UnityEngine.UIElements;
using System.Collections.Generic;
public class CharacterCreatorController : MonoBehaviour
{
private UIDocument uiDocument;
private TextField characterName;
private DropdownField ageStage;
// Sliders for HEXACO
private Slider honestySlider;
private Slider emotionalitySlider;
private Slider extraversionSlider;
private Slider agreeablenessSlider;
private Slider conscientiousnessSlider;
private Slider opennessSlider;
// Toggles for traits
private Toggle creativeTrait;
private Toggle ambitiousTrait;
private Toggle bookwormTrait;
private Button createButton;
void OnEnable()
{
uiDocument = GetComponent<UIDocument>();
var root = uiDocument.rootVisualElement;
// Query for all the elements by name
characterName = root.Q<TextField>("character-name");
ageStage = root.Q<DropdownField>("age-stage-dropdown");
honestySlider = root.Q<Slider>("honesty-slider");
emotionalitySlider = root.Q<Slider>("emotionality-slider");
extraversionSlider = root.Q<Slider>("extraversion-slider");
agreeablenessSlider = root.Q<Slider>("agreeableness-slider");
conscientiousnessSlider = root.Q<Slider>("conscientiousness-slider");
opennessSlider = root.Q<Slider>("openness-slider");
creativeTrait = root.Q<Toggle>("creative-trait-toggle");
ambitiousTrait = root.Q<Toggle>("ambitious-trait-toggle");
bookwormTrait = root.Q<Toggle>("bookworm-trait-toggle");
createButton = root.Q<Button>("create-character-button");
// Register a callback for the button click
createButton.RegisterCallback<ClickEvent>(evt => OnCreateCharacterClicked());
}
private void OnCreateCharacterClicked()
{
Debug.Log("--- Character Creation Data ---");
Debug.Log($"Name: {characterName.value}");
Debug.Log($"Age Stage: {ageStage.value}");
Debug.Log("--- Personality ---");
Debug.Log($"Honesty-Humility: {honestySlider.value}");
Debug.Log($"Emotionality: {emotionalitySlider.value}");
Debug.Log($"Extraversion: {extraversionSlider.value}");
Debug.Log($"Agreeableness: {agreeablenessSlider.value}");
Debug.Log($"Conscientiousness: {conscientiousnessSlider.value}");
Debug.Log($"Openness: {opennessSlider.value}");
List<string> selectedTraits = new List<string>();
if (creativeTrait.value) selectedTraits.Add("Creative");
if (ambitiousTrait.value) selectedTraits.Add("Ambitious");
if (bookwormTrait.value) selectedTraits.Add("Bookworm");
Debug.Log($"Traits: {string.Join(", ", selectedTraits)}");
Debug.Log("-----------------------------");
}
}
Run the scene, fill out the form, and click the "Create Character" button. You should see all the data you entered printed neatly in the Unity console.
Conclusion
Excellent work! You've successfully built a functional character creation screen using Unity's modern UI Toolkit. You've structured the layout with UXML, applied styles with USS, and captured user input with a C# script.
Key Takeaways:
- UI Toolkit separates UI into UXML (structure), USS (style), and C# (logic).
- Flexbox is the primary system for creating flexible and responsive layouts in UI Toolkit.
- UI elements are created in the UI Builder and configured in the Inspector, where you assign them a unique
name. - C# scripts access UI elements using
root.Q<ElementType>("element-name"). - User interactions like button clicks are handled by registering callbacks (e.g.,
RegisterCallback<ClickEvent>).
Right now, our captured data only exists in the Unity console. In the next lesson, we will take the next critical step: passing this character creation data from Unity to our Rust backend via the FFI for validation. This will be the first time our frontend and backend truly communicate with complex, structured data.