Search Unity

Sorting Sprite Renderer over a Mesh Renderer

Discussion in 'World Building' started by Danil0v3s, Dec 28, 2020.

  1. Danil0v3s

    Danil0v3s

    Joined:
    Sep 22, 2014
    Posts:
    45
    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.
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    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?
     
  3. Danil0v3s

    Danil0v3s

    Joined:
    Sep 22, 2014
    Posts:
    45
    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)
     
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    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.
     
  5. Danil0v3s

    Danil0v3s

    Joined:
    Sep 22, 2014
    Posts:
    45
    Hey! Sorry for the delay... holidays...

    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?
     
  6. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Mathf.Cos takes radians, not degrees.
     
  7. Danil0v3s

    Danil0v3s

    Joined:
    Sep 22, 2014
    Posts:
    45
    Yeah, I know about that. However
    • 1 + Cos(30) = 1.15425
    • 1 + Cos(31) = 1.91474
    • 1 + Cos(32) = 1.83422
    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?
     
  8. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    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)
    .
     
  9. Danil0v3s

    Danil0v3s

    Joined:
    Sep 22, 2014
    Posts:
    45
    But I'm already assuming that 30 is in radians. Or is that wrong?
     
  10. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    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.
     
  11. Danil0v3s

    Danil0v3s

    Joined:
    Sep 22, 2014
    Posts:
    45
    Hey, sorry for being harsh or rude, didn't mean at all!

    Now, when I use the 30 * Mathf.Deg2Rad I get a result like this


    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?
     
    Last edited: Jan 6, 2021
  12. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    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.
     
    Aratow and Danil0v3s like this.
  13. Danil0v3s

    Danil0v3s

    Joined:
    Sep 22, 2014
    Posts:
    45
    Thank you very much! It does work flawlessly! I didn't think about dividing, I did all kinds of things but dividing...

    Thank you again!
     
    JoeStrout likes this.