The main thing preventing us from considering UI Toolkit is we’ve solved hard UI problems using standard UI and can’t imagine them being solved in UI Toolkit.
So the goal of this thread is to gather all such challenges, then someone will hopefully show how they can be solved.
I’ll start with the things I can think of (I warn you, it’s a long list):
Text has a solid-color, rectangle background that resizes automatically to fit when the text gets longer [answered]
Vertical scroll view, with content size fitter [answered]
Grid layout with center-aligned items, also in second row of items (standard UI doesn’t have it btw) [answered]
Grid layout. When an item is clicked, it scales up covering 30% of all neighbouring items (both previous and next items) [answered]
Template item under horizontal layout, being desactivated at start and “Instantiated” to become 10 items when populated. And second version, using prefab file rather than template item. [answered]
Object Pool of layout with 1000 items (though there are 1000 elements of the list, we show only 9 visible layout items, recycling ones getting hidden when user scrolls) [answered]
Object Pool for popups - if user opens popup, closes, and opens it again, the second opening uses the desactivated one [answered]
Preventing aliasing of a texture with 1-pixel wide white line on black background, which is slowly rotated clockwise, on lower resolutions, in world-space UI (the solution is MipMaps, will it work for UI Toolkit?) [answered]
Dragging elements between different hierarchies (not within one parent) [answered]
Flexible layout (3 items taking constant 10%, 30%, and 60% of height when resized up) [answered]
Layout with child Image being the background covering all layout’s space (it was solved by LayoutElement.IgnoreLayout = true)
Mask showing part of the child image (standard way masks work) [answered]
Image that “blurs” everything behind it (optional) [answered]
Button running async callback on click [answered]
Inheriting Button to display log every time user clicks (in the future I’ll need to replace standard button with button doing sfx & vfx)
Resizing UI panel to be constrained by safe area for mobile UI
What is mechanism for Canvas Scaler? [answered]
Function moving image to be placed at 60% of parent’s height (with canvas scaler mechanism) (takes .6f as parameter)
Function moving child Image (Image’s parent takes all screen width and height) to be where mouse pointer is, but don’t use IOnPointer…, but rather take mousePosition from the input, then recalculate to get position on the UI (should work with canvas scaler mechanism)
Function resizing Image to take 60% of height, starting at bottom and resizing up (takes .6f as parameter)
I’ve heard rumors that you can’t reference buttons or text in the editor, and that text doesn’t allow SetCharArray or the features of SetText that prevents garbage generation.
Hi, I see you provide a diferents solutions to those topics, maybe you can help me with my doubt, I would like to know if a can modify the way the Hierachy in UI Builder show when an element its display is NONE, like how we can see gray an object that is disable, sometimes I just want to have a quickly feedback about the state of one Visual Element, or if is one in Display flex that shouln´t be in that state. I try hiden tag but i would like something more automatic thank u in advance
Just set the width/height of your scrollview to 100%
You can emulate this with flex-wrap: wrap, and by adding margins to your elements, although you’d have to use code to remove margins from the final row of elements. There’s also a ready made grid solution in the app-ui package, you might want to check that out.
I’m not sure how exactly you want that to look, but I’ve achieved a similar effect by saving the layout of grid elements on click, then setting their position to absolute like this:
I would then move the clicked element to the bottom of the hierarchy and animate the expansion with DoTween
You can easily do that with VisualTreeAsset.CloneTree(myRootElement), then you’d simply set display to None. You cannot use the gameobject hierarchy with UI Toolkit, but you can emulate it by creating a script that instantiates an asset and removes it in OnEnable/OnDestroy. I use this method, and it makes it much easier to debug ui views and their field values, with the downside being having to write a lot of boilerplate code.
element.style.display = visible ? DisplayStyle.Flex : DisplayStyle.None; Really don’t see what’s so challenging about this
Don’t think that’s possible even in 2d ui, unless unity improved that behavior in recent versions
You mean in UI Builder? Yeah, good luck with that one lmfao, that’s a core design issue with the whole system
flex-basis/height: x% are your friends here, very simple to do
Right now only possible with custom shaders and extremely limited, I did this a while ago for a museum and it was an absolute pain
This is only possible to do if you have 2 panels - one for the background and another for the image. After the background panel is rendered to a texture, you’d run a blur material through that texture and use it as the background for your image panel. The problem here is that unity provides no AfterPanelRendered callbacks, meaning you can’t blur the background and display it immediately in the image panel, this causes visible 1 frame lag in the blurred area.
Unfortunately, you can’t just clone the UI Toolkit package and modify unity’s shit code, so what I did is - I created a separate api bridge assembly that uses Harmony to runtime patch unity’s code. It looks somewhat like this:
[HarmonyPatch]
private class UIEPatches
{
[HarmonyPatch(typeof(UIElementsRuntimeUtility), nameof(UIElementsRuntimeUtility.RenderOverlaysBeforePriority))]
private static bool Prefix(int displayIndex, float maxPriority)
{
if (UIElementsRuntimeUtility.currentOverlayIndex < 0)
return false;
for (List<Panel> sortedPlayerPanels = UIElementsRuntimeUtility.GetSortedPlayerPanels(); UIElementsRuntimeUtility.currentOverlayIndex < sortedPlayerPanels.Count; ++UIElementsRuntimeUtility.currentOverlayIndex)
{
if (sortedPlayerPanels[UIElementsRuntimeUtility.currentOverlayIndex] is BaseRuntimePanel panel)
{
if (panel.sortingPriority >= (double)maxPriority)
break;
if (panel.targetDisplay == displayIndex)
{
if (panel is RuntimePanel runtimePanel)
{
BeforePanelRepaint?.Invoke(runtimePanel.panelSettings);
}
UIElementsRuntimeUtility.RepaintOverlayPanel(panel);
if (panel is RuntimePanel runtimePanel2)
{
AfterPanelRepaint?.Invoke(runtimePanel2.panelSettings);
}
}
}
}
return false;
}
}
The unfortunate side effect of this method is that it can’t be used in IL2CPP