Are there any plans to add some kind of automatic code generator for the name of UI elements in UI-Builder? Did the type create a button by naming it, and the attached element immediately added a position in the Dictionary<string, UIElement>
?
This is what this attribute is for: Unity - Scripting API: UxmlElementAttribute
In Competitive Action Multiplayer Template the following is shown:
namespace Unity.Template.CompetitiveActionMultiplayer
{
[RequireComponent(typeof(UIDocument))]
public class SessionInfo : MonoBehaviour
{
const float k_UpdateSessionInfoDelay = 2f;
const string k_RedColor = "#ff5555";
const string k_OrangeColor = "#ffb86c";
const string k_GreenColor = "#50fa7b";
static class UIElementNames
{
public const string SessionInfoContainer = "SessionInfoContainer";
public const string BinaryInfoLabel = "BinaryInfo";
public const string ArgsInfoLabel = "ArgsInfo";
public const string RightInfoLabel = "RightInfo";
public const string HardwareInfoLabel = "HardwareInfo";
public const string ConnectionInfoLabel = "ConnectionInfo";
public const string ShowSessionInfo = "ShowSessionInfo";
}
VisualElement m_SessionInfoBanner;
VisualElement m_SessionInfoContainer;
Label m_BinaryInfoLabel;
Label m_RightInfoLabel;
Label m_HardwareInfoLabel;
Label m_ConnectionInfoLabel;
Label m_ArgsInfoLabel;
Label m_ShowSessionInfo;
string m_RightInfo;
string m_ConnectionInfo;
string m_MachineInfo;
ProfilerRecorder m_SystemMemoryRecorder;
ProfilerRecorder m_GcMemoryRecorder;
ProfilerRecorder m_CpuRecorder;
ProfilerRecorder m_CpuToGpuRecorder;
ProfilerRecorder m_GpuRecorder;
ProfilerRecorder m_GcCountRecorder;
ProfilerRecorder m_DrawCallsRecorder;
ProfilerRecorder m_FilesOpenRecorder;
ProfilerRecorder m_FilesBytesReadRecorder;
float m_Timer;
async void OnEnable()
{
m_SessionInfoBanner = GetComponent<UIDocument>().rootVisualElement;
GameInput.Actions.DebugActions.ToggleSessionInfo.performed += OnToggleSessionInfoVisibilityPerformed;
m_SessionInfoContainer = m_SessionInfoBanner.Q<VisualElement>(UIElementNames.SessionInfoContainer);
m_BinaryInfoLabel = m_SessionInfoBanner.Q<Label>(UIElementNames.BinaryInfoLabel);
m_RightInfoLabel = m_SessionInfoBanner.Q<Label>(UIElementNames.RightInfoLabel);
m_HardwareInfoLabel = m_SessionInfoBanner.Q<Label>(UIElementNames.HardwareInfoLabel);
m_ConnectionInfoLabel = m_SessionInfoBanner.Q<Label>(UIElementNames.ConnectionInfoLabel);
m_ConnectionInfoLabel.RegisterCallback<ClickEvent>(CopySessionCode);
m_ArgsInfoLabel = m_SessionInfoBanner.Q<Label>(UIElementNames.ArgsInfoLabel);
m_ShowSessionInfo = m_SessionInfoBanner.Q<Label>(UIElementNames.ShowSessionInfo);
var visibilityButton = await InputSystemManager.IsMobile ? "4 Finger Tap" : "i";
m_ShowSessionInfo.text = $"Toggle visibility with <color={k_RedColor}>{visibilityButton}</color>";
// https://docs.unity3d.com/Manual/frame-timing-manager.html
m_SystemMemoryRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Memory, "System Used Memory");
m_GcMemoryRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Memory, "GC Used Memory");
m_CpuRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Internal, "CPU Main Thread Frame Time", 15);
m_CpuToGpuRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Internal, "CPU Render Thread Frame Time", 15);
m_GpuRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Internal, "GPU Frame Time", 15);
m_GcCountRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Internal, "GC Allocation In Frame Count", 15);
m_DrawCallsRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Internal, "Draw Calls Count", 15);
m_FilesOpenRecorder = ProfilerRecorder.StartNew(ProfilerCategory.FileIO, "File Handles Open", 15);
m_FilesBytesReadRecorder = ProfilerRecorder.StartNew(ProfilerCategory.FileIO, "File Bytes Read", 60);
m_RightInfo = $"{{0}} | {{1}}";
var hasArgs = HasArgs(out var args);
m_ArgsInfoLabel.style.display = hasArgs ? DisplayStyle.Flex : DisplayStyle.None;
m_ArgsInfoLabel.text = args;
m_ConnectionInfo = $"Player: \"{{0}}\" on \"{Environment.MachineName}\" | {{1}}";
var burst = BurstCompiler.IsEnabled ? " +BC" : "";
var qualityPreset = $"{QualitySettings.names[QualitySettings.GetQualityLevel()]}";
var targetFrameRate = Application.targetFrameRate > 0 ? Application.targetFrameRate.ToString() : "OFF";
var vSync = QualitySettings.vSyncCount > 0 ? $"{QualitySettings.vSyncCount}th @ {Screen.currentResolution.refreshRateRatio.value}hz" : "OFF";
m_MachineInfo = $"<color=#8be9fd>{SystemInfo.operatingSystem} | {SystemInfo.deviceModel} | {SystemInfo.processorType} | {SystemInfo.graphicsDeviceName}</color>";
m_BinaryInfoLabel.text = $"{Application.productName} by {Application.companyName} | Ver {Application.version}{burst} | {GetBuildType()} | QSetting:{qualityPreset} | TargetFPS:{targetFrameRate} | VSync:{vSync}";
UpdateSessionInfo();
}
}
}
And at the moment, I can’t figure out how the names of UI elements in UI-Builder and C# code synchronize.
It’s literally just a property: Unity - Scripting API: UIElements.VisualElement.name
The default name is defined by the aforementioned attribute, or by the type name if not using that constructor.
I often set a default name in the constructor with my own custom controls.
Yes, thanks, I figured it out. I mean, I have very little experience in Unity and especially in the UI Toolkit, my main activity is the development of desktop applications with a UI based on WPF.
If you create a UI element in WPF and give it a name, for example Name=“btnSSH”:
Then the logic code in C# is automatically synchronized and this element will be available in Visual Studio by its name:
And in general, where MainWindow.xaml is automatically divided into two files, the design markup is located, and MainWindow.xaml.cs, where the program logic is located.
I want to understand how such a mechanism works in the UI Toolkit, and whether it exists at all
In UI Toolkit the name of a visual element is just a data point. A visual element of the same type can have any name, and it’s only real significance is for the sake of querying a visual element within a hierarchy, or styling it with a USS selector using its name.
And in general relying on the names of things is not a robust way to code your systems.
In any case UI Toolkit doesn’t work the way you’re used to. In Unity, at the most basic level, you would query visual elements via a monobehaviour component on a game object to manipulate or hook into various visual elements.
On a more advanced level you probably would code custom controls to have the specific required behaviour.
What you’re describing does sound useful but not something that exists in Unity at the moment.
Thanks, I think that’s exactly what I wanted to know!