Initial commit
This commit is contained in:
86
skills/unity-uitoolkit/SKILL.md
Normal file
86
skills/unity-uitoolkit/SKILL.md
Normal file
@@ -0,0 +1,86 @@
|
||||
---
|
||||
name: Unity UI Toolkit
|
||||
description: Assists with Unity UI Toolkit development - UXML structure, USS styling, C# VisualElement manipulation, data binding, and custom controls. Use when implementing UI Toolkit interfaces.
|
||||
allowed-tools: Read, Write, Glob
|
||||
---
|
||||
|
||||
# Unity UI Toolkit
|
||||
|
||||
Assists with Unity UI Toolkit development including UXML markup, USS styling, C# VisualElement API, and modern UI patterns.
|
||||
|
||||
## What This Skill Helps With
|
||||
|
||||
### UXML Structure
|
||||
- Proper element hierarchy and naming conventions
|
||||
- Common controls: TextField, Button, Toggle, Slider, ObjectField, ListView
|
||||
- Layout containers: VisualElement, ScrollView, Foldout, TwoPaneSplitView
|
||||
- Data-driven UI with templates and bindings
|
||||
|
||||
### USS Styling
|
||||
- Class-based styling and selectors
|
||||
- Flexbox layout (flex-direction, justify-content, align-items)
|
||||
- USS variables and dark theme optimization
|
||||
- Pseudo-classes (:hover, :active, :disabled)
|
||||
- Transitions and animations
|
||||
|
||||
### C# VisualElement API
|
||||
- Query API: `rootElement.Q<Button>("my-button")`
|
||||
- Event handling: `.clicked +=` and `.RegisterValueChangedCallback()`
|
||||
- Dynamic UI creation with constructors
|
||||
- Data binding with `Bind()` and `SerializedObject`
|
||||
|
||||
### Best Practices
|
||||
- UXML for structure, USS for styling, C# for logic
|
||||
- Name elements for Query API access
|
||||
- Use classes for styling, not inline styles
|
||||
- Cache VisualElement references in fields
|
||||
- Proper event cleanup in `OnDestroy()`
|
||||
|
||||
## Common Patterns
|
||||
|
||||
**Editor Window Setup:**
|
||||
```csharp
|
||||
public void CreateGUI() {
|
||||
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("path/to.uxml");
|
||||
visualTree.CloneTree(rootVisualElement);
|
||||
|
||||
var button = rootVisualElement.Q<Button>("my-button");
|
||||
button.clicked += OnButtonClick;
|
||||
}
|
||||
```
|
||||
|
||||
**USS Class Toggle:**
|
||||
```csharp
|
||||
element.AddToClassList("active");
|
||||
element.RemoveFromClassList("active");
|
||||
element.ToggleInClassList("active");
|
||||
```
|
||||
|
||||
**Data Binding:**
|
||||
```csharp
|
||||
var so = new SerializedObject(target);
|
||||
rootVisualElement.Bind(so);
|
||||
```
|
||||
|
||||
## Unity Version Requirements
|
||||
|
||||
- **Unity 2021.2+** for runtime UI Toolkit
|
||||
- **Unity 2019.4+** for editor-only UI Toolkit (limited features)
|
||||
|
||||
See [ui-toolkit-reference.md](ui-toolkit-reference.md) for complete API documentation.
|
||||
|
||||
## When to Use vs Other Components
|
||||
|
||||
**Use this Skill when**: Building UI Toolkit interfaces, writing UXML/USS, or manipulating VisualElements in C#
|
||||
|
||||
**Use unity-ui-selector skill when**: Choosing between UGUI and UI Toolkit for a project
|
||||
|
||||
**Use @unity-scripter agent when**: Implementing complex UI logic or custom VisualElement controls
|
||||
|
||||
**Use EditorScriptUIToolkit templates when**: Generating new UI Toolkit editor windows with UXML/USS files
|
||||
|
||||
## Related Skills
|
||||
|
||||
- **unity-ui-selector**: Helps choose between UGUI and UI Toolkit
|
||||
- **unity-template-generator**: Generates UI Toolkit editor script templates
|
||||
- **unity-script-validator**: Validates UI Toolkit code patterns
|
||||
203
skills/unity-uitoolkit/ui-toolkit-reference.md
Normal file
203
skills/unity-uitoolkit/ui-toolkit-reference.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# UI Toolkit Quick Reference
|
||||
|
||||
## Common VisualElement Types
|
||||
|
||||
### Input Controls
|
||||
- `TextField` - Single/multi-line text input
|
||||
- `IntegerField`, `FloatField`, `Vector3Field` - Numeric inputs
|
||||
- `Toggle` - Boolean checkbox
|
||||
- `Button` - Clickable button
|
||||
- `Slider` - Value slider with optional input field
|
||||
- `EnumField` - Dropdown for enum values
|
||||
- `ObjectField` - Unity Object reference picker
|
||||
|
||||
### Layout Containers
|
||||
- `VisualElement` - Generic container (like `<div>`)
|
||||
- `ScrollView` - Scrollable area
|
||||
- `Foldout` - Collapsible section
|
||||
- `TwoPaneSplitView` - Resizable split panel
|
||||
- `ListView` - Data-driven list with virtualization
|
||||
|
||||
### Display Elements
|
||||
- `Label` - Text display
|
||||
- `Image` - Sprite/Texture display
|
||||
- `HelpBox` - Info/Warning/Error message box
|
||||
- `ProgressBar` - Progress indicator
|
||||
|
||||
## USS Flexbox Layout
|
||||
|
||||
```css
|
||||
.container {
|
||||
flex-direction: row; /* or column */
|
||||
justify-content: flex-start; /* flex-end, center, space-between */
|
||||
align-items: stretch; /* flex-start, flex-end, center */
|
||||
flex-grow: 1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
```
|
||||
|
||||
## USS Common Properties
|
||||
|
||||
```css
|
||||
/* Spacing */
|
||||
margin: 10px;
|
||||
padding: 5px 10px;
|
||||
|
||||
/* Sizing */
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
min-width: 50px;
|
||||
max-height: 300px;
|
||||
|
||||
/* Background */
|
||||
background-color: rgb(50, 50, 50);
|
||||
background-image: url('path/to/image.png');
|
||||
|
||||
/* Border */
|
||||
border-width: 1px;
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 4px;
|
||||
|
||||
/* Text */
|
||||
color: rgb(200, 200, 200);
|
||||
font-size: 14px;
|
||||
-unity-font-style: bold; /* or italic */
|
||||
-unity-text-align: middle-center;
|
||||
```
|
||||
|
||||
## Query API Examples
|
||||
|
||||
```csharp
|
||||
// By name (must set name in UXML)
|
||||
var button = root.Q<Button>("my-button");
|
||||
|
||||
// By class
|
||||
var items = root.Query<VisualElement>(className: "item").ToList();
|
||||
|
||||
// First match
|
||||
var firstLabel = root.Q<Label>();
|
||||
|
||||
// All matches
|
||||
var allButtons = root.Query<Button>().ToList();
|
||||
|
||||
// Complex query
|
||||
var activeItems = root.Query<VisualElement>()
|
||||
.Where(e => e.ClassListContains("active"))
|
||||
.ToList();
|
||||
```
|
||||
|
||||
## Event Handling
|
||||
|
||||
```csharp
|
||||
// Button click
|
||||
button.clicked += () => Debug.Log("Clicked!");
|
||||
|
||||
// Value change
|
||||
textField.RegisterValueChangedCallback(evt => {
|
||||
Debug.Log($"Changed: {evt.previousValue} -> {evt.newValue}");
|
||||
});
|
||||
|
||||
// Mouse events
|
||||
element.RegisterCallback<MouseDownEvent>(evt => {
|
||||
Debug.Log($"Mouse down at {evt.localMousePosition}");
|
||||
});
|
||||
|
||||
// Cleanup
|
||||
void OnDestroy() {
|
||||
button.clicked -= OnButtonClick;
|
||||
}
|
||||
```
|
||||
|
||||
## Data Binding
|
||||
|
||||
```csharp
|
||||
// Bind to SerializedObject
|
||||
var so = new SerializedObject(targetObject);
|
||||
rootVisualElement.Bind(so);
|
||||
|
||||
// Manual binding
|
||||
var property = so.FindProperty("fieldName");
|
||||
var field = new PropertyField(property);
|
||||
field.BindProperty(property);
|
||||
```
|
||||
|
||||
## Custom VisualElement
|
||||
|
||||
```csharp
|
||||
public class CustomElement : VisualElement
|
||||
{
|
||||
public new class UxmlFactory : UxmlFactory<CustomElement, UxmlTraits> { }
|
||||
|
||||
public new class UxmlTraits : VisualElement.UxmlTraits
|
||||
{
|
||||
UxmlStringAttribute customAttribute = new UxmlStringAttribute
|
||||
{ name = "custom-value" };
|
||||
|
||||
public override void Init(VisualElement ve, IUxmlAttributes bag,
|
||||
CreationContext cc)
|
||||
{
|
||||
base.Init(ve, bag, cc);
|
||||
((CustomElement)ve).customValue = customAttribute.GetValueFromBag(bag, cc);
|
||||
}
|
||||
}
|
||||
|
||||
private string customValue;
|
||||
|
||||
public CustomElement()
|
||||
{
|
||||
AddToClassList("custom-element");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Tips
|
||||
|
||||
1. **Use USS classes** instead of inline styles
|
||||
2. **Cache VisualElement references** instead of repeated queries
|
||||
3. **Use ListView** for large lists (virtualized)
|
||||
4. **Avoid excessive rebuilds** - update only changed elements
|
||||
5. **Use USS variables** for maintainable themes
|
||||
6. **Minimize UXML nesting** for better performance
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
❌ **Querying before CreateGUI finishes**
|
||||
```csharp
|
||||
// Wrong
|
||||
void OnEnable() {
|
||||
var button = rootVisualElement.Q<Button>(); // null!
|
||||
}
|
||||
|
||||
// Correct
|
||||
public void CreateGUI() {
|
||||
visualTree.CloneTree(rootVisualElement);
|
||||
var button = rootVisualElement.Q<Button>(); // works!
|
||||
}
|
||||
```
|
||||
|
||||
❌ **Forgetting to name elements**
|
||||
```xml
|
||||
<!-- Wrong: Can't query by name -->
|
||||
<ui:Button text="Click" />
|
||||
|
||||
<!-- Correct -->
|
||||
<ui:Button name="my-button" text="Click" />
|
||||
```
|
||||
|
||||
❌ **Not cleaning up events**
|
||||
```csharp
|
||||
// Memory leak!
|
||||
button.clicked += OnClick;
|
||||
|
||||
// Correct
|
||||
void OnDestroy() {
|
||||
button.clicked -= OnClick;
|
||||
}
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- Unity Manual: UI Toolkit
|
||||
- Unity Scripting API: UnityEngine.UIElements
|
||||
- Unity Forum: UI Toolkit section
|
||||
- Sample Projects: UI Toolkit samples on GitHub
|
||||
Reference in New Issue
Block a user