Create a custom control
Understand the basics of creating and using custom controls.
읽는 시간 5분최근 업데이트: 22일 전
A good custom control is abstract, self-contained, and recurring.
A Slide Toggle is a good example of a custom control:
- It's abstract. You can use it to adjust settings, such as volume, brightness, scale, and power.
- It's self-contained. You give it a label and an initial value. A Slide Toggle triggers an event when its state changes.
- It's recurring. You can use it in multiple places in an application.
The menu bar of your application isn't a good example of a custom control:
- It's not abstract. It's specific to your application.
- It's not self-contained. It probably has dependencies on other parts of your application.
- It's not recurring. There is probably only one menu in your application.
After you have created a custom control, you can style it with USS and add logic to handle events in C#.
Create and use a custom control
To create a custom control, do the following:
- Add the attribute to the custom control class definition.
UxmlElement - Declare the custom control class as a partial class.
- Inherit it from or one of its derived classes.
VisualElement
For example:
using UnityEngine;using UnityEngine.UIElements;[UxmlElement]public partial class ExampleElement : VisualElement {}
You can use your custom controls in UXML and UI Builder after you create them.
The following example UXML document uses the custom control:
<ui:UXML xmlns:ui="UnityEngine.UIElements"> <ExampleElement /></ui:UXML>
By default, the custom control appears in the Library tab in UI Builder. If you want to hide it from the Library tab, add the attribute.
HideInInspectorInitialize a custom control
Custom controls inherit from . A isn't a MonoBehaviour and therefore doesn't receive any of the callbacks that a MonoBehaviour receives, such as , , , and .
VisualElementVisualElementAwake()OnEnable()OnDisable()OnDestroy()You can initialize a custom control in its constructor. However, if your application needs it, you can delay initialization until the custom control is added to the UI. To do this, register a callback for an . To detect that your custom control has been removed from the UI, use the callback.
AttachToPanelEventDetachFromPanelEventpublic CustomControl(){ RegisterCallback<AttachToPanelEvent>(e => { /* do something here when element is added to UI */ }); RegisterCallback<DetachFromPanelEvent>(e => { /* do something here when element is removed from UI */ });}
UI Toolkit dispatches these two events for all elements and doesn't need a custom subclass. For more information, refer to Panel events.
VisualElementStyle custom controls with USS
Use USS to customize the look of a custom control the same way as a built-in control. You can also create USS custom properties to style a custom control.
To interact with custom USS properties for a custom control in C#, use the structure and the event.
CustomStylePropertyCustomStylesResolvedEventCustomStylePropertyUI Toolkit dispatches for any element that directly receives a custom USS property. It dispatches the event for any element that a selector matches, for selectors where the rule contains the value of the custom property. UI Toolkit doesn't dispatch the event for elements that inherit the value. The event holds a reference to an object. You must use its method to read the effective value of a . This method has overloads for different types of .
CustomStylesResolvedEventICustomStyleTryGetValue()CustomStylePropertyCustomStylePropertyFor a custom style with a custom control example, refer to Create custom style for a custom control.
Handle events for custom controls
For detailed information on how to handle events for custom controls, refer to Handle events.
- Unity dispatches keyboard events to the currently focused element. To handle keyboard events for a custom control, set properties related to .
focus - To handle touch and mouse input events, register callbacks for the relevant event types, such as pointer events and mouse events, in the constructor.
Best practices and tips
-
Expose properties that a custom control represents and other functional aspects of its behavior as UXML properties, and expose properties that affect the look of a custom control as USS properties.
-
Use a namespace that's unique, short, and readable to avoid name collisions with other elements.
-
Keep UXML attributes primitive. Data that you can specify in UXML is limited to a set of primitive data types. UXML doesn't support complex data structures or collections. Pass complex data to your custom controls at runtime via C# scripts or data binding, not in UXML.
-
In C#, expose USS classes or names as constants. This allows you to locate elements by class or name using UQuery.
-
Adopt the BEM standard for USS classes. This allows you to address every element with a class list selector.
-
Use static callbacks for a lower memory footprint. When you register an instance method to be used as a callback, you might create unnecessary allocations. To avoid allocations, use anonymous static lambda functions that call into regular C# static methods. You can retrieve the context of the current element through theproperty.
EventBase.currentTarget -
Render custom geometry through thecallback for custom controls. For an example usage that renders a partially filled circle, refer to the RadialProgress example.
generateVisualContent -
Custom controls are convenient. However, you might achieve the same outcomes with the following:
- Assemble your UI from existing elements, and change their styles and properties.
- Use UXML templates. Use regular C# s to add logic that pertains to the specific UI Document that holds your UI. To learn how to use
MonoBehaviours to control UI in a UI Document, refer to Create your first runtime UI. To achieve encapsulation, create properties and methods inside yourMonoBehaviourthat internally fetchMonoBehaviours with UQuery and manipulate their properties.VisualElement