Hey all, I’ve tried searching before posting but couldn’t find anything that would explain what I need to do in order to fix this issue.
For some context: I am writing a famous game client from scratch and the game uses a 3D World with 3D models but the entities (npcs, players, mobs, etc) are all Sprite Renderers with Billboards.
The problem is whenever I’m close to a 3D object, the sprite renderer “goes through” the mesh. Just like this:
I’ve tried using sorting groups for both the sprite and the mesh and also have tried changing the inspector to Debug and then changing the mesh sorting layer, no result at all.
This is what I’m trying to achieve:
The entities move along the X and Z axis and Y is for the tile height.
Pause the game when it’s in that poking-through-the-mesh state, switch to the scene view, and move the scene camera around until you can get a good look at what’s going on. Is the sprite mesh actually intersecting the scenery mesh?
Yes, it is. I could get something working but don’t know if it will cause more problems down the line.
I’ve removed the X rotation from the Billboard, so the Sprite is always straight (poiting up), then I scaled the Y of the sprite parent to 1 + Mathf.Cos(30)
That’s the right solution, and kudos to you for figuring it out. Normally sprites face the camera, but if you let these sprites face the camera, they’re going to poke through things. To avoid that they need to stand up straight in the world, but since the camera is looking at them at an angle and the artist assumed they would be drawn straight on, you have to stretch them out to compensate.
There may be other solutions involving multiple cameras, but this is a nice simple solution that should get you going.
So, I just found what I was afraid of, the camera can pitch some degrees, I’d say from 30 to 35. While having the sprite height calculated with 1 + Mathf.Cos(30) works for a 30 degree angle, how could I get the same result while changing the camera angle? I tried applying the Cos to the current angle but as result the sprite height goes to somewhere near zero then goes back to normal height. I sure am missing something very basic here, would you enlighten me?
The sprite just “goes wild” when applying that formula. Does this technique have a name so I can lookup or maybe you could explain the math behind it. Or am I missing something here?
You say you know about that, but you’re still passing degrees into Cos. Stop that. It should be 1 + Mathf.Cos(30 * Mathf.Deg2Rad), not 1 + Mathf.Cos(30).
Yes. Radians measure angles between 0 and 2Pi, roughly 6.28. Or, sometimes, between -pi and pi (so between -3.14 and 3.14). Degrees measure angles between 0 and 360 (or sometimes between -180 and 180). 30 is clearly an angle measurement in degrees.
And when using a “full billboard” which changes the rotation of the object, it gets like this
It seems like in the one with the radians thing I’m not scaling on x as well, so when I scale in the X by 1 + Mathf.Sin(angle * Mathf.Deg2Rad) it gets huuuge. Do I need to do any division by the PIXELS_PER_UNIT I’ve used when parsing those sprites?
Don’t scale X. The X is fine, it’s only Y that needs stretching. And it appears that adding the cosine of the angle was never the right math to use; it just happened (by sheer coincidence) to work out approximately correct when you mistook degrees for radians. I’m afraid I didn’t check the math, but just assumed it was right.
Some quick sketching on a napkin suggests to me that the right scaling factor (in Y) would be 1/cos(ang), or in Unity terms, 1 / Mathf.Cos(ang * Mathf.Deg2Rad). With a camera angle of 30 degrees, this gives you a scaling factor of 1.1547. At 35 degrees (a sharper angle), it’ll be 1.220775.