1
\$\begingroup\$

I am creating a 2.5D game similar to Paper Mario. I want the sprites that I import to Unity to be the perfect dimensions so that quality is not affected by the camera's position. If I'm understanding correctly, I need to know how many pixels the sprite is taking up on screen, using my camera's current position, is that correct?

For example, if I want my character to be this size, while my default camera position is this, how do I know what dimensions to make the sprite?

Game Display: 1920 X 1080P

This is the CinemachineVirtualCam following the sprite.

enter image description here

Here is a screenshot of the MainCamera:

enter image description here

I imagine there must be an easy way to figure this out, as many devs seem to know exactly how big to make their sprites. Thanks for taking the time to read!

Kind regards,

\$\endgroup\$
2
  • \$\begingroup\$ I think it would help if you clarify your setup a bit more. I see you have a perspective camera but you’re speaking about sprites. Are you aiming for 2D, 3D, or 2.5D? \$\endgroup\$
    – Adam B
    Sep 21 at 5:11
  • 1
    \$\begingroup\$ Sure! I'll clarify in the question. \$\endgroup\$ Sep 21 at 12:39

1 Answer 1

0
\$\begingroup\$

I'll pretend for a moment that your sprite is billboarded, so it always exactly faces the camera.

At a depth of \$z\$ units in front of a perspective camera with (half) vertical field of view \$fov\$, the camera sees a rectangular slice of the world that's exactly...

$$h_\text{world} = z \cdot 2 \tan (\text {fov})$$

...world units tall. That corresponds to \$h_\text{screen}\$ pixels, the height of your screen/window.

So if your screen is 1080 pixels tall, and your camera has a 30° field of view, and is following your character a distance of 5 units along its z axis, then each unit of world space at your character's depth maps to:

$$ppu = \frac {h_\text{screen}} {h_\text{world}} = \frac {1080} {(5) \cdot 2 \tan (30^\circ)} = \frac {108} {\frac 1 {\sqrt 3}} \approx 187.06$$

187.06 pixels per unit of world space.

You can use this as the Pixels Per Unit setting in the inspector when importing your sprite, and your sprite's vertical resolution should be the character's height in world space multiplied by this number. (So if you wanted your character to be 1.5 world units tall, that would be \$1.5 \cdot 187.06 \approx 281\$ pixels tall).

(Using a field of view whose tangent ratio is a rational number will help you get a nice neat integer here instead of a messy irrational that could experience rounding errors)

Or, you can use any power of 2 times this ppu, and similarly bump up the resolution of your sprite by the same power of two, so that the \$i^{th}\$ mipmap exactly matches the screen resolution.

Now, when the sprite is not exactly billboarded to the camera... it gets complicated. Your vertical height will now be foreshortened by the camera's tilt, which will cause the sprite to span fewer on-screen pixels top-to-bottom. But just reducing its height won't fix that, because the rows of texels will no longer be evenly spaced - rows farther from the camera will cluster closer together, and the columns won't be straight verticals, but converging diagonals. That means you will not be able to get a 1:1 match between the grid of sprite texels and the grid of screen pixels, and some interpolation and blurring will have to occur somewhere.

One way around this - without tilting all your characters back so they stand on a diagonal, leading to weird clipping with vertical walls and such - is to not tilt your camera downward. Instead, have it look directly horizontally. Then, use an oblique frustum to shift the image plane vertically, so that you lift up the horizon on the screen, and the portion below the horizon where the camera is looking "down" fills your view. This shift does not disturb the spacing or parallel-ness of a grid drawn in the XY plane, so it won't distort your sprites.

\$\endgroup\$

You must log in to answer this question.

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