16
\$\begingroup\$

I'm looking at the new 2D features introduced in Unity 4.3, and I think I might be missing something.

To me it looks like they are designed for high-res 2D games, where scaling the sprites is ok, but it is unsuitable for pixel-art games.

A pixel-art sprite is designed to be displayed exactly 1:1 pixels on the screen: scaling destroys it (linear up-scaling is an exception, i.e. you may scale it 2x, 3x, 4x etc.).

However I've found no way to "just display it as-is", apparently Unity insists in scaling it to whatever resolution it sees fit: I may control the Camera.size parameter, and the "pixels to units" parameter of the sprite, but I didn't manage to obtain this result.

\$\endgroup\$
  • 1
    \$\begingroup\$ If I'm not wrong, "Organ Trail" game was made entirely on Unity3d, before 4.3. \$\endgroup\$ – felipe Nov 24 '13 at 14:54
19
\$\begingroup\$

This article gives some useful explainations, even if that's before 4.3 came out:

If you’re going for the “pixel art” look then the camera’s orthographic size is of critical importance; this is the trickiest part of nailing 2D in Unity.

The orthographic size expresses how many world units are contained in the top half of the camera projection. For example, if you set an orthographic size of 5, then the vertical extents of the viewport will contain exactly 10 units of world space. (The horizontal extents are dependent on the display aspect ratio.)

Recall that your sprite quad is 1 unit to a side. That means the orthographic size tells you how many sprites you can stack vertically in the viewport (divided by 2).

To render the pixel-art look cleanly, you need to ensure that each pixel of the sprite’s source texture maps 1:1 to the viewport display. You don’t want source pixels being skipped or doubled-up, or your sprites will look distorted and “dirty”. The trick to ensuring this 1:1 ratio is to set an orthographic size that matches your vertical screen resolution divided by the pixel height of a sprite.

Let’s say you’re running at 960x640, and you’re using 64x64 sprites. Dividing the vertical screen resolution (640) by the pixel height of a sprite (64) yields 10, the number of 64x64 sprites that can be vertically stacked in 640 pixels. Remember that the orthographic size is a half-height, so your target orthographic size in this case is going to be 5 (one-half of 10). It should look like this:

If you set your orthographic size to half or double that target you may still get usable results, because the sprite’s vertical size will still divide evenly into the viewport’s vertical size. But if you set the orthographic size incorrectly, you will see some pixels skipped or doubled, and it will look very bad indeed:

Variable Resolution

You don’t need to be confined to a single, fixed resolution in order to render clean pixel art. The simplest way to handle variable resolutions is to attach a custom script to your camera which sets the orthographic size according to the current vertical resolution and a known (fixed) sprite size:

// set the camera to the correct orthographic size
// (so scene pixels are 1:1)
s_baseOrthographicSize = Screen.height / 64.0f / 2.0f;
Camera.main.orthographicSize = s_baseOrthographicSize;

While that is a simple fix, it does have a drawback: as the screen resolution decreases, you’ll see less and less of the world, and sprites will take up more and more of the screen. That’s the consequence of keeping a 1:1 ratio between source and screen pixels: a 64x64 sprite takes up more apparent space at 640x480 than it does at 1920x1200. Whether this is a problem or not depends on the needs of your specific game.

If you want your sprites to remain the same apparent size regardless of screen resolution, then simply set the orthographic size to a fixed value and leave it there regardless of the screen resolution. The drawback there is that your sprites will no longer have a 1:1 source-to-screen pixel ratio. You can mitigate the ill effects of that by only allowing resolutions which are exactly half or exactly double your target resolution.

(some emphasis added)

This obviously works better if the height resolution is divisible by the sprite size, but even when it isn't, it still gives a good approximation of a decent result.


TL;DR: cameraSelf.orthographicSize = screenH / (float)spriteSize / 2f;

\$\endgroup\$
  • 5
    \$\begingroup\$ Another useful thing is to set texture filtering to 'Point'. \$\endgroup\$ – felipe Nov 24 '13 at 14:56
  • \$\begingroup\$ @Felipe good point: I forgot about that because I already figured it out. \$\endgroup\$ – o0'. Nov 26 '13 at 14:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.