Image on the left is rendered on a poorly calibrated camera while the one on the right is properly calibrated. (click on image to see full-res)
The secret to making your pixelated game look nice is to ensure that your sprite is rendered on a nice pixel boundary. In other words, ensure that each pixel of your sprite is rendered on one screen pixel (or any other round number). The trick to achieving this result is tweaking the camera’s orthographic size (and live with the consequences).
On an orthographic camera, the orthographic size dictates how many units in world space the screen’s height is divided into. So on a screen height of 1080 with orthographic size of 5, each world space unit will take up 108 pixels (1080 / (5*2)). It’s 5 * 2 because orthographic size specifies the size going from the center of the screen to the top.
Therefore if your Sprite’s Pixels Per Unit (PPU) settings is 108, it will be rendered nicely.
To apply this on an actual project requires a bit more considerations and planning ahead. Since you can’t tweak the physical resolution of the target device and you only have a very limited range of PPU (by way of asset bundle variant), the only real number that you can play with is the orthographic size.
Changing the orthographic size will have the effect of increasing or decreasing the visible world space. This impacts your game code directly and need to be accounted for. Here’s a table with various scaling scenarios
* Orthographic size = ((Vert Resolution)/(PPUScale * PPU)) * 0.5
There are three well known techniques to handle the scaling and it is quite plausible that you will employ all three in your project.
For a small difference, a simple ‘thick border’ will suffice. Depending on your game’s design, a few percentage bigger or smaller than your reference screen size can be easily filled with the thick border.
The overall screen size grows but the art size stays the same. This can be easily dealt with by increasing the thickness of the floor/roof.
However, when the screen increases beyond a certain size, a thick border will no longer be practical.
If you start out with a reference screen height of 768 and PPU of 32, going to 1080 is going to be troublesome as your assets will not scale nicely.
The table above illustrates scaling a game starting from 768 all to way to 1536 with three alternatives on how to deal with 1080. The most interesting number to look at is the orthographic size. The ideal situation is that as your screen size grows, the orthographic size remains the same. This will ensure that your assets will take up the same amount of screen space as they do with your reference resolution.
From the table above, using an alternate sprite at PPU 48 would create a visible world space that’s only 6.25% smaller than your reference size. This could be easily dealt with using the thick border approach.
If your screen grows big enough, we could display your sprites at 2x by applying a scaling factor to the calculation of the orthographic size. For the case of 1440, we could keep using the PPU 32 sprites but calculate the orthographic size as such (1440/(2*32)) * 0.5 which gives you 11.25.
This means, each world space units will contain 64 screen pixels. This effectively tells the engine to render 32 pixels from the sprite onto 64 pixels on screen. This gives a nice whole number factor of 2 which will look good at the same time giving you a world space that’s just 6.25% smaller than your reference setup.
This technique does not require new assets to be created.
* The PPU 32 sprites are now rendered twice as big but still look fantastic. This only works for whole number enlargement.
These other settings are essential to make things as crisp as possible.
On the sprite:
In Render Quality Settings:
(Optional) Turn on pixel snapping in the sprite shader by creating a custom material that uses the Sprite/Default shader and attaching it to the SpriteRenderer.
To implement the above system requires 2 parts.
Check out a demo project that demonstrates this approach
Even with all these number tweaking, there are still a few issues:
Making pixel perfect 2D games is possible with the current version of Unity. However, as detailed above, there are consequences and known issues, but they are not insurmountable nor are they blockers. Long live retro style games!