Hi all, sorry if this is a newbie question, I searched around for quite a bit trying to find a best practice for how to do this and felt like everything I found was less than ideal.
So here is my issue:
I am making a game with a lot of 3D effects combined with 2D sprites. (think something like hearthstone for lack a better analogy)
What I would really like is to have these 2D sprites just respect their z-indexes when it comes to rendering order the same way that all the 3D objects do. But it seems that is impossible to rely on.
I figured I could show which sprites are in different depths just by using layers. But this has the effect of also making all of my 3D objects appear behind those sprites. (as far as I can tell it is impossible to put them into another layer)
Are quads the answer here? It seems less than straightforward to put a sprite image on them. (I am also not sure if they have all the features I want like png transparancy, image rendering at different anchors, etc)
What is the best practice here? I feel like my use case must be a common/simple one, but I am having a difficult time figuring out a straightforward and simple way to solve it. I am hoping that I am missing something simple/obvious.
I’m not sure what the best practice is, but why can’t you rely on z-order? If you keep the sorting layer and sorting order of all your sprites at the default, they should render based on where they are in 3D space right?
Here is the problem as I understand it (and I could be naive here so please tell me if there is something I am missing):
For many sprites I have a parent object that has a transform component attached. I notice that as soon as a transform component exists on a parent gameobject, whatever I z-index I add to my sprite no longer matters. So if I want my sprite to align to a gameboard based on where it is placed inside of a parent gameobject I cannot then change its z-index to be different from its parent.
I would love to be able to change the z-index and have it adjust based on where it is inside the parent gameobject, but as far as I can tell this is not possible.
For this reason I believe that I cannot use z-order. (and please correct me if I am missing something or am wrong here)
Just in case, I’d like to clarify that when I say z-order, I mean the Z position in the transform component. If you have a 2D or 2.5D camera, the Z position should be what controls the render order of sprites by default.
The Sprite Renderer’s sorting layer should be left at Default, and the order in layer should be 0 for all sprites. That will allow the sprite’s position coordinates to control its rendering.
I just did a few tests with parenting sprites to other objects, and the z-order always works for me; like for 3D objects, it should not be dependent on the parent’s transform, just where it is in 3D space. The one big difference between a sprite and a plane is that sprites cannot intersect with other sprites; one sprite is always completely rendered over the other.
If you could take some screenshots of the parenting issue, you’re experiencing, that would be helpful in figuring out what’s wrong, because I can’t replicate the issue.
I have tried all different types of camera settings for transparancy sort mode and projection. I currently have a transparency sort mode of custom z-axis and a perspective camera.
I am attaching screenshots of objects in my inspector, my camera settings in project settings and my camera in the inspector. Board is a parent of cardonboard, cardonboard is a parent of HexCardface.
-board
–cardonboard
—hexcardface
Changing position.z of hexcardface has zero effect in my game, I have no idea why. It is like its forced to align to its parent cardonboardobject on the z axis. (although changing position.z of cardonboard DOES seem to have an impact)
I assumed when I started that things would work exactly as you described. I am kind of embarrassed to be honest, because I have spent a long time on this and cannot figure out how to make it work the way you described. I feel like I must have some trivial setting wrong somewhere that stops me from using unity as its intended.
So as a side note, scaling parent objects can cause problems, as it messes with the child’s rotation and scale. It’s not super convenient, but you can change the source sprite’s size in the project tab by changing the “Pixels Per Unit.” This likely isn’t the issue, but I thought I’d mention it.
The Transparency Sort Mode that you’re using really stands out to me as being the issue. Currently, you have it set so that the object with the lowest Z world position will always be rendered in front, which will get really confusing with child objects, as their local X,Y,Z coordinates are not necessarily the same as their world coordinates.
For example: If I rotate my parent sprite by 90 on its X axis, the child’s Z position axis now controls its Y position in the world.
Apologies if the way I’m explaining that is confusing, but in essence, can you try setting the Transparency Sort Mode to Default or Perspective and see if that fixes things?
For reference, I’m testing this in Unity 2020.3.11f1, I made a new project with the 2D template, and I changed the Main Camera in the scene from Orthographic to Perspective.
Everything you are saying makes sense, I actually started with a perspective camera. It makes no difference, I have tried all combinations of camera types and transparancy sort modes. I have also tried turning off all rotations in my code.
I doubt this is a camera issue. The thing that really sticks out to me is that z position just gets completely ignored when the gameobject with a sprite attached is a child of cardonboard. (I have similar issues with other objects in my code) If I make everything a parent of the root object z positions all seem to work just fine though.
I am on 2020.3.3f1 right now. (doubt it makes a difference but I could upgrade)
So I finally solved it, I couldn’t find this information while googling every related search term I could so I will leave the answer here in case it prevents someone else from wasting as much time as I did:
The problem is that the z-scale is set to zero in CardOnBoard. When the z-scale is set to zero it has the effect of compressing everything inside that component into a plane. Changed it to 1 and things worked.
Seems obvious in retrospect, I am a little embarrassed. Its an easy mistake to make as I was using Vector2D everywhere to set scale which has the hidden effect of setting the z scale to zero on all my components.
I appreciate your responses and patience with my incorrect newbie assumptions though, you were more useful than you may realize! You prevented me from continuing to think that it was normal for 2D objects to force everything inside of them to align on a plane and led me to eventually look towards the correct place. Thanks for your generous offer of looking at my project as well!
TLDR: Dont set z-scale to zero unless you want to compress everything inside your gameobject into a plane.
I would not have guessed that, just tested it myself and yeah it completely locks the child’s Z axis. I had no idea that Z scale affected sprites at all, learned something new.