I’m creating some Image elements from C#, they’re dynamic backgrounds for a text element. The image objects are being added to the same parent GameObject the text lives under.
No matter what I do, I can’t get the text to render on top of the Images. Since the text doesn’t have a sortOrder I’ve tried setting the z positions on all elements, but it doesn’t make a difference.
I must be doing something wrong then. When I made this post, I was adding the Image elements to the parent of the Text element. Just in case unity doesn’t like the fact that the Image and Text became siblings, I made a new GameObject to nest the text under. That doesn’t work either.
→ TextBubbleBackground ← Image elements added via code here.
→ GameObject
→ TextBubbleText
No matter what the Image(s) always cover my Text.
EDIT: Playing around with transform SetAsFirstSibling / SetAsLastSibling methods. Even thought the objects are no longer siblings, they work as long as I set the index for every sibling.
If I am using a grid order layout and want my objects in a specific order, simply changing their order in the hierarchy will not work, they will be physically moved. Is there another option?
Please mind the downsides and consequences. Every another canvas breaks batching thus increasing draw calls amount. One call for things below the new canvas, one for the new canvas with children and one for something on top of it. This may really kill performance if it is done say in a backpack item prefab. Even a small backpack with 8x8 items may result in 3*64=192 draw calls made (instead of just one!) just to render your backback.
Unity Team at Unite recommended breaking things into smaller canvases for better performance, since every little change in one big canvas makes the whole canvas redraw.
While you don’t need to make every little item a separate canvas, since that’ll introduce problem that LanVision described, but you better divide your big canvas into separate smaller canvases that have own update logic, independent from other elements.
That is, however, a 2 year old info. Please let me know if this have changed.
No, that hasn’t changed. However, following recommendations blindly isn’t going to do any good if one doesn’t understand the underlying reasons.
Dividing canvases can greatly increase performance if there are changing layout elements. If a layout element has changed, these changes will “propagate” to parenting layouts in the same canvas. This usually means that the whole canvas is going to be recalculated. So it is generally a good idea to enclose such changing elements into a separate smaller canvases because such layout changings won’t go beyond the canvas enclosing it.
So, canvas dividing is good when there are too many UI calculations which can be constrained into smaller canvases.
But think a minute about a general backpack full of items. They are usually just put in their places once and aren’t really going to change after that. There are no layout changes and no propagations going to happen at all in this case. So there really is no need to produce any more canvases besides just one. But the added draw calls overhead may and will decrease performance here (more calls means more impact).
All in all, fellow developers, please think of what you are doing, even if it is ‘recommended’ by Unity team. Because every such recommendation is intended to solve some problem which probably doesn’t actually exist in your project. And bear in mind the price you may have to pay for implementing them.
EDIT: By “changing” I of course mean changes in size, positions etc, not changing one image to another one.
What if we have two canvases. I have a canvas by default in the scene. When scene runs, a new canvas appears from the previous scene ( because of Dont destroy on load on the canvas of the previous canvas). Now after the scene started running, the new canvas always appears in the end of hierarchy. Due to this reason all the elements of the previous canvas are rendered beneath the new ui. This is the order of the hierarchy:
Gameobjects → Default canvas → New Canvas from the previous scene.
I want a particular gameObject from the Default canvas rendered above the new canvas…
If anybody runs into this problem, here you are: i just found that on Canvas component there is a Sort order field, that does the trick, at least it did for me.
I was just about to say that . . if you seperate it in a different canvas, just use “Sort Order” (put the index of the canvas as high for the one you needed in the back)
It may help conceptually to think of it as rendering order. Items are rendered from top to bottom, meaning the first item on the list is behind the last item.
This is probably the most useful piece of information in this entire thread! Seriously, knowing THIS one little bit of information solves the problem that all the back and forth BS on new canvases doesn’t.
All I had to do was put a number in front of the name, to force a sorting order in the hierarchy, but it still didn’t seem to work right, until I read it was “bottom up”. I changed my numbering order and BAM! Everything is sorted as intended, without resorting to extra canvas trickery.
You have to take in count 2 sceneries here: Static UIs and Dynamic UIs created/added on runtime, the first one is solved sorting by Hierarchy in the Canvas it self, but the second one is solved using SetSiblingIndex(int index)
Is usually common that some already created UI elements in Hierarchy need to be on Top of the new runtime created UI elements, is in these cases when SetSiblingIndex become pretty useful: