1
\$\begingroup\$

I'm trying to re-create the same effect of sprites/billboards that all entities in a game such as Don't Starve have.

What is the best way of doing this in Unity? Certain things come to mind:

  1. Have a script that at all times perfectly rotate the object to directly face the camera. This seems very inefficient.
  2. Hard-code the rotation of all objects at a certain angle so that they look flat to the camera. This seems inconvenient since I want to use my Q and E keys to rotate the camera 90 degrees (to be able to view the world from 4 directions).
  3. Some sort of billboarding tool that Unity already has?

Since my camera rotation can change, I need all of the sprites to rotate in real time, so that at all times they face the camera. Are sprites even used for this, or is something else used to display the entities? (like billboarding, I'm not very familiar with how it works).

For context, I am planning to just use a regular 3D world where the camera will be angled down to look at the entities, and I want to achieve an effect similar to this:

Don't Starve Example

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Have a script that at all times perfectly rotate the object to directly face the camera. This seems very inefficient. Usually billboarding is done in a similar way, where the camera's rotation is also applied to a sprite, this ensures that the sprite will pretty much look at the camera. Have you noticed any performance issues to suggest this is inefficient? \$\endgroup\$ Aug 22, 2022 at 10:27

1 Answer 1

1
\$\begingroup\$

If you need to change rotation potentially every frame, then a script that runs every frame is pretty much the way to go.

In the example screenshot there are maybe 30 sprites on screen. It would be very difficult to cause a noticeable performance impact from doing anything a mere 30 times per frame. So as TomTsagk says in a comment, you should definitely test out this simplest, most direct option first, and profile it to verify whether there's any real problem that might force you to do something more complex.

If your camera only rotates in discrete hops, you could set up this script to run only when the camera moves (so, in the same script where you listen for the Q/E key press to start the camera move, you also fire off the billboarding update). Then at least it's not running redundantly when the camera angle stays fixed.

You want to orient the sprites or quads to face along (the negation of) the camera's forward vector. That means you don't need to change the sprite rotation when the camera translates, only when it rotates.

Technically, you could also accomplish this by abuse of a particle system, which have built-in billboarding options. Those compute new billboarded quads for every particle every frame without significant performance impact, even for thousands of simultaneous particles on screen. But the indirection of routing all your sprite positioning and animation updates through a particle buffer is likely to get onerous and sap more productivity than it is worth.

Lastly, you could implement the billboarding effect in a shader, repositioning the vertices to snap them to face the camera just before rasterizing the sprite. This is a little complicated to do without breaking sprite batching though, as the vertices would somehow need to figure out where the sprite's pivot is, to rotate the billboard around that. Normally that info has already been baked down by that stage of the pipeline, so it would be extra work to reconstruct.

So, I'd say: try the simple rotation script first. Profile it. If you find it has an unacceptable cost, update your question with your findings and we can explore potential fixes. But those fixes are themselves complicated enough to be a net drain on your productivity if they're not truly needed.

\$\endgroup\$
3
  • \$\begingroup\$ What I was hoping for was something along the lines of "abuse of a particle system" you mentioned, because I thought there was a better way to do this in Unity. However, considering I'll have animations linked to my sprites (sprite for the head, body, limbs, all of them separately animated), I do now see that the simplest approach is in fact the best. My camera will indeed rotate in fixed 90 degree segments, so I'll take your advice so that it doesn't have to run every frame. \$\endgroup\$
    – caleidon
    Aug 23, 2022 at 11:08
  • \$\begingroup\$ As for the implementation, would it be okay to make a "FaceTheCamera" script I can attach to each entity, and then when my camera rotates, go through all the entities and call GetComponent to get that script, and inside of it change the rotation of the transform, or is there a more efficient way of doing this that I'm missing? \$\endgroup\$
    – caleidon
    Aug 23, 2022 at 11:09
  • 1
    \$\begingroup\$ I'd recommend caching a list of active FaceTheCamera instances — for instance, a static variable holding a shared list that each instance adds itself to in OnEnable and removes itself from in OnDisable. Then you can iterate that list directly, with no GetComponent searching in the middle of your hot loop. \$\endgroup\$
    – DMGregory
    Aug 23, 2022 at 11:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .