UI, sorting multiple objects based on height, efficiently?

Hey there!

I have 1 canvas that handles 15 objects that move around the screen.
The issue is: For example the legs of creature A are now on top of the head of creature B.
I want to fix this by giving the objects with a higher Y-value a lower sorting order.
(The same system Isometric rendering works, layering the ‘farthest back’ behind)

I know I can do this by sorting the hierarchy, or by adding canvas components to the objects and changing their sorting layer.

The problem is, is that those two methods are terribly inefficient.
What is the best way to solve this?

WHAT?! For 15 items?! I find that hard to believe. Do you know this from actually analyzing it in the profiler? (Window → Analyze → Profiler)

Meanwhile, I see you bandying about “y value” and “sorting order,” neither of which applies to Canvases… keep this in mind:

Three (3) primary ways that Unity draws / stacks / sorts / layers / overlays stuff:

In short, as far as the Standard Rendering Pipeline,

  1. The default 3D Renderers draw stuff according to Z depth - distance from camera.

  2. SpriteRenderers draw according to their Sorting Layer and Sorting Depth properties

  3. UI Canvas Renderers draw in linear transform sequence, like a stack of papers

If you find that you need to mix and match items using these different ways of rendering, and have them appear in ways they are not initially designed for, you need to:

  • identify what you are using
  • search online for the combination of things you are doing and how to to achieve what you want.

There may be more than one solution to try.

For instance, you may even use multiple co-located cameras (along with different Layers and LayerMasks drawn to different-depth Cameras) to more-explicitly control apparent draw ordering.

Additional reading in the official docs:

And SortingGroups can also be extremely helpful in certain circumstances:

Other rendering pipelines may have other ways of layering (HDRP and URP). Go see the latest docs for details.

There’s lots of third party open source packages available as well, such as this:

1 Like

No worries!! I am not currently having issues! :open_mouth: I just tried the method below with 600 objects, with 4 sprites each (waaaayyy higher than I would ever have normally (60-ish max)), and there wasn’t a huge performance hit.

I’ve set it to the canvas option now, which I’ve made work like so:
The gameobjects have their own script/class. They store both the RectTransform.localPosition.y and the Canvas, which overrides the sorting order.
I loop through these scripts, and set the sorting order according to the inverse-Y-level. (When moved, of course, we wouldn’t want this to happen when idling).

In another program I wrote, I did apply your suggestions, but that was indeed much easier to do in world-space. Even on my old phone, I am able to run about 3000-4000 objects, depending on the collisions happening per frame.

Do not worry!! There is about 0 performance drain right now, but I was more worried that if all objects had their own canvas, the meshing might not work efficiently. (More Draw Calls).
So far no issues.

Thanks for the reply as always!