After andy touch asked about the 2D workflow in unity, I mentioned my trouble with 2D sorting. He asked for more info so… here goes
(These experiences are from Ori and the blind forest which doesn’t use the SpriteRenderer but the same applies to sprite renderers. It’s mostly relevant for 2.5D games using a perspective camera)
Our artists laid out the tiles and used the z axis as depth. Obviously for transparent stuff, the higher the z value, the earlier it should get drawn. This draw ordering should be consistent to what the artist laid out and should never change. Sounds easy but this is a mess right now in unity.
Here’s the story of what we went through:
Just a regular perspective camera and sprite renderers. Pops under movement and rotation… this is because stuff is sorted on distance from camera, moving or rotating this changes the distance and thus the order, sigh…
Use this (Unity - Scripting API: TransparencySortMode) to make camera act like an orthographic camera. A little better, but under rotation this still fails. Plus, this doesn’t work in the scene view - which would mean art between scene view and game view doesn’t match up. We hacked it into the scene view, but it still isn’t stable under rotation. Artists rotate the camera all the time to get a better view so that’s still not workable.
Use “Order in Layer” based on the actual Z position of the object to enforce some more order. Better, but if objects are on the same order, stuff still pops.
Add a random offset to that z position to force stuff to be in another order than a close neighbour. However… turns out order in layer is not actually an int, values only go from -32768 to 32767. Not nearly enough to give a precise enough range.
Use the sorting order on materials too. Turns out though you can only go up so high with those too before unity does weird stuff… Still not precise enough.
Use above, and additional sorting layers spanning ranges of z, with more precision in the center layer and… you get the point, we shipped with an incredibly complex system JUST to keep tiles stabily sorted
Luckily, there’s just three small things that need to be done:
Add a TransparencySortMode.ZAxis. Don’t use distance to camera but just the actual z position of the object.
Apply this TransparencySortMode to the scene view. (Ideally you’d just pick the default sorting mode in the project and it sets it to all cameras)
When objects do still sort the same, they should be rendered based on some well defined order - probably based on transform order like the UI is.
Lastly, if the sortingOrder could be usable in it’s full int range, that would be good too, but I imagine that’s an optimization.
Hope that helps
TL;DR: 2D Sorting in unity only works for super simple cases, it’s not stable, workarounds are hard. Fix is easy
In our game, we’re using an puppet animation library called Spriter, to animate our characters, and it uses z-position to sort character pieces internally.
This means we need to rely on Sorting Order to actually sort our different units, and we’re doing so based on their y-position on screen. In order to avoid z-fighting (when y values are tied) we need to incorporate a random offset in addition to the y-position, and once we do that we begin running out of precision values.
Great to hear unity will take a look at this! Thanks
@gskinner : Yeah we had that exact issue with our random offsets.
I do feel that ideally we don’t have to mess around with sorting order at all. I’m guessing you’re game is isometric? I think there was a prototype in the unity 2D alpha’s doing isometric sorting. It was implemented by calculating a proper sorting order by iterating over all objects though Lots of performance and GC overhead in that prototype…
Ideally the camera sorting behaviour would be extended even further to allow for different types of 2D games (perhaps a TransparencySortMode.Standard2D, TransparencySortMode.Isometric2D etc. assuming in principle z-axis depth, y-axis as isometric depth etc.) but I wanted to keep the proposed changes simple.
Here’s my situation with sprite sorting (Unity 5.3.0f4):
I am making a 2D game.
I have 3 different materials (shaders) on my sprites.
I need control over sort order (really anything would work).
Sort order simply does not work correctly. It seems to be sorting by material (which I would call a bug).
I have put all of my sprites into the same “Sorting Layer” (Default), and I use the sprite “Order in Layer” to sort them.
It appears that the renderer is sorting by MATERIAL (or shader) first, and THEN the “Sorting Layer” and “Order in Layer”. So that means I cannot control the sort order for different materials.
Here’s my example (in order back-to-front):
Head (order 1 material1)
Nose (order 2 material3)
Eye (order 3 material1)
Highlight (order 100 material2)
Note: I’ve named my materials in the order I created them which may be related to the order they are rendered.
I’ve got an instance of material3 sandwiched between a pair of material1, and material2 is a UI element that needs to render on top. If “Order in Layer” worked as advertised, this should work but it does not. Instead, I’m seeing this:
Head (order 1 material1)
Eye (order 3 material1)
Highlight (order 100 material2)
Nose (order 2 material3)
I have tried putting them on different “Sorting Layer” but that had no impact. I also tried messing with their z-depth, but that also had no impact.
So is this a known bug? Is there some work-around?
I want to echo PV Loon’s request to allow for Z sorting based on Z-position instead of distance to the camera. That would solve a lot of problems elegantly.
So small update on this, I got an e-mail from some unity folks that they intend to fix this. They only mentioned making sorting order a full int though. After explaining again why this is only a small patch and we need z position sort (thanks Xelnath!), they added me on skype aaand… never heard from them again! I hope they still have some time for this at some point
I’d just like to say that if there any sort of better sorting solution made for Z coordinates, please please make something similar for Y coordinates, and just do X while you’re at it. Give the camera an option for sorting solutions. The Box2D implementation is XY only, and as such, there are XY Isometric games where Z is not closed to the camera, it’s Y.
Other than that, better sorting would be awesome. You have no idea (well, many people probably have a very good idea) how frustrating it was to wrestle with the sorting and issues that accompany it at times.
Trying to build a 2d Sprite game using mecanim. Is this the same issue as the one I’m having where if you have two mecanim objects with multiple parts standing near overlap of each other, that various body parts and pieces from one enemy will overlap the neighboring enemy?
Has anyone tried out the Sorting Group Component in the 2D Experimental Preview? It would be great to get some feedback on it and if it solves some of your issues :).
yeah I’ve tried the experimental 2D preview and while the sorting group is neat, it doesn’t solve any of the issues mentioned here. Heck, in the demo for the sorting group, try rotating the camera (perspective) and you’ll see the sorting flicker… (almost all of the demos in the preview do FYI). Not a huge deal for a pure 2D game but for 2.5D games this is terrible to work with and we’re back to the hacks mentioned above.
I hope the 2D preview can address the issues mentioned here and implement some of the suggestions. Just the Z-Axis based sort + scene view sorting like the main camera will help so much.
Generally I feel like users shouldn’t have to mess with sorting layers & groups manually unless we really want absolute control, we just need a good default sorting. Sorting on Z axis & hierarchy order would definitely work for pure 2D games and for 95% of 2.5D games already.
If you want to do isometric too maybe you would want to sort on a custom axis but heck even there Z axis sorting would still be much better than this sortingOrder troubles
Hi Arthur,
Thanks for the reply.Yes the Sorting Group currently focuses on 2D mode Scene View.
We are working on a solution based on yours and other suggestions here but it was not ready to get into Preview.1.
Currently I use a system similar to OrderInLayer = Z position. With some division (math) to extend its limitations.
My camera is Perspective, with sprites billboarded.
However, some of my objects are very complex (many individual pieces that need to have specific order in layer, within the object itself.)
I was interested in trying Sorting Groups, but don’t want to waste the time based on what the OP says.
Since every object (Characters, Plants, Trees) are multiple sprites, I need two things:
For each object (one parent gameobject) to sort all its sprites it has to a single layer, based on Z-Axis. (All body part sprite pieces that make up a single character object, will render infront/behind other objects based on Z-Axis, despite their order in layer among themselves).
For all children of that object, to be able to sort to any order in layer, while maintaining the above overall layer. (ex. I could have six arms, one behind another, with the sixth arm at (BaseLayer + 6), but all arms will still render behind a different character object that is 1 unit infront of their Z-Axis.
Do Sorting Groups solve this? It looks like it does in the little gif on the page, but it’s hard to read even after watching it repeatedly. I’m trying to find a more thorough explanation or preview of this feature, but found this instead.
I thought this is exactly what Sorting Groups are for, but the OP’s problem is strikingly similar to my own, minus the camera rotation issues. I do not rotate the camera, but it is a 3D world with 2D sprites, perspective camera, and setting OrderInLayer to Z-position is the only thing that has ever worked for me up until this point. And although it works, it is far from perfect when the character walks too close to another complex object.
Hi Carter,
Sorting Groups only work with Sorting Layer and OrderInLayer. If you are setting the OrderInLayer then it should work for you. If you need axis distance sorting, as the OP, we are currently working on a solution. Coming soon.
I just tried the new sorting group feature, it’s great and works well, but i am having trouble to do something i already did on my project but manually and with lot of time
So there is a boss, a huge humanoid boss (with long legs, torso, arms …), and my character needs to be able to run between his legs, so my character is always in front of the boss except against his right or left leg.
In the boss sorting group, i set “Default” as sorting layer, then i added a nested sorting group in his left leg and put “Front” as sorting layer, it works only locally (even if i set -9000 in sorting order it still appear in front of his body so it’s great !) but the leg still appears behind my character.
I think nested sorting group with different sorting layer should be ignored and should manage their children themself