So, I’m working on a property editor style control in uGUI and am having lots of issues caused by the fact that the transform hierarchy is the draw order.
One example of this: I have a combo box which is a prefab’d control. It contains a scroll rect to hold the items which comes up when the user clicks on it.
When you open the combo box, the items in the menu after the combo box control draw over the drop down list panel because they are later in the transform hierarchy (and must be for the layout group to order them correctly.)
To fix this, I added another rect which draws after the entire property editor draws, and reparent the drop down panels to it. However, now that the drop down panel has a new parent, it doesn’t move or scale correctly.
Is there any way to change the draw order without changing the transform hierarchy? The coupling of hierarchy == draw order == layout is convenient, but an extremely tight coupling since you often want those to be different, as in this case.
I agree 100%. Dummy parents a decent work-around, but it feels a bit dirty. Personally, I think a “priority” setting would be nice, so that for all elements of the same priority the hierarchy is used to determine the drawing order. That way we could easily set the odd ones out the be drawn either earlier or later.
In many GUI systems, dropdown boxes (and things like them, such as tooltips) are implemented as separate windows. That approach should work for you here; create a new canvas (Screen Space - Camera), ensure it’s in the same sorting layer as your main panel, but with a smaller ‘Order In Layer’ value, and use that to hold your vertical list of elements. It should render on top of the rest of the GUI as you require. The potentially tricky part then is to get it to go away when clicked on (and potentially even harder, get it to go away when you click somewhere else entirely).
No currently it is only tied to the hierarchy. But maybe submit a feature request with your example and we could possibly take a look for a later release.
There really should be a sorting order for GUI components. Dropdowns of various types and information dialogs currently need a lot of special attention to go in front of everything. A simple priority setting like the sprite system already has would be much better. It would be even better if the root object had its sorting order in such a frontmost dialog case, and the rest of the hierarchy inherited that and added 1 for each step down.
So a reusable infobox could have a priority of 100, making sub-elements 101 etc., similar for a dropdown (but starting at 10, 20, whatever makes sense). Just expose one simple setting and make children inherit
@orb I am finding this exactly. I have a persistent popup window setup in the first scene. With Screen Space - Overlay the next scenes Canvas is then on top of the previous. It doesn’t seem obvious how we manage the z order of the canvas in Screen Space - Overlay.
That won’t actually work here, because moving the object to a different canvas means it will have a different parent, and thus move/scale differently as the screen is resized. And even if it could be made to work through hackery (possibly by having a dummy object in each canvas and copying the vertex positions from one to the other - ugh), it certainly wouldn’t be a robust solution able to work with different types of canvas’s, etc…
For screen space - Overlay canvas’s the z position of the root canvas’s is what will determine the sorting order as we have no other way to know exact positioning of the canvas in the hierarchy.
I just needed to prototype a GUI with multiple panels, some draggable, that needed to be clickable to front. I came up with a solution that feels sort of dirty, but it works for now.
Each panel is on its own canvas
Dragging changes the canvas Z coordinate to -10
End drag moves it back to 0 (order is preserved)
Each canvas has a component that changes the depth to -10 and back to 0 on click (this strangely works fine, and only responds to clicks on actual controls)
@phil-Unity I seem to remember looking at this, although I couldn’t move a screen space - overlay in z unless I make it a child. Thanks for the info and I should add, obvious
NGUI currently uses “depth,” which is similar to the priority system used for the sprite renderer. For UIs of moderate to high complexity, I find using numerical priorities to be much more painful than relying on the hierarchy order. Often is the time I have found myself reordering dozens of prio values yet again, all the while wishing for this feature (we shipped our game on 4.2). So I wouldn’t want to lose that.
As for the original problem, wouldn’t the use of sorting layers address that?
I’d like to raise my hand here in support of this. It is incredibly obnoxious to have to choose between “render tooltip on top” and “use all the powerful anchor/pivot features for auto-layout”.
Right now the only way to do what I want is 1) create tooltip, 2) Canvas.ForceUpdateCanvases, 3) reparent with SetParent(true), and if I wanted to have a tooltip that moves with resolution changes, I have to do that again every time the resolution changes, and if I want to have a tooltip that follows an object around the screen (like a talk bubble), I have to do that every FRAME. Augh.
We just need an “always on top” checkbox on a canvas renderer or canvas group, and all it has to do is pop those element renderings out of the normal sequence and stick them at the end.
I was hoping the Z of the rect transform would have this effect, since it is exposed, but no.
Thank you again for your responsiveness. I look forward eagerly to the day I can graduate to my pro license: You all have made me feel confident that it is a safe investment for the future.
What’s the correct workflow for adding a Canvas to a UI component? I have run into issues when I copy the Canvas component from my base canvas and add it via Paste Component.
When I use that process to add a Canvas component to a UI element (in this case a Panel, i.e. an object with a Canvas Renderer and Image script on it), I get four instances of this error when I run the game:
m_TransformInfo.localAABB.IsValid()
And when I exit play mode, I get four instances of this: