Hello everybody,
since the beginning of my 2D pixel art game development I researched from time to time about how to make the camera movement as smooth as possible without any stutters or ripple/warping effects on the sprites and still being pixel perfect.
But up to now I’am not 100% satisfied with my camera movement. Since I found some very good sources regarding this topic over time I thought its maybe good to share this information. On one site I hope it can help somebody with similar problems and on the other side maybe I have a misconception or overlooked something.
1. Basics - Orthographic Size
When you draw your sprites or your canvas for a pixel art game you draw (unsurprisingly) single pixels ^^. But you need to choose a resolution (native resolution) for your drawings in Photoshop, Pyxel Edit, aseprite, Pixaki, Paint or whatever program you like to use. To have a pixel perfect image in your game at the end you need to scale your native resolution by an integer N (1, 2, 3, …) because there are no half pixels. Images look blurry or the drawing pixels aren’t square if they aren’t pixel perfect. That means
N * drawing pixel = screen pixel
must always be fulfield to a have a pixel perfect image on the screen.
The following image:
is a close up pixel perfect „screenshot“ (with a smartphone camera) from the game FEZ on a screen with a resolution of 2560x1440. You basically see that 1 drawing pixel (e.g. one of the yellow cord pixel of the red hat) consists of 4 screen pixel. So the native resolution is 2560x1440 divided by 4 = 640x360.
These sources have some good visual explanetaions:
- c# - Getting "giggly" effect when slowly moving a sprite - Stack Overflow
- Unity Blog
- https://www.youtube.com/watch?v=yI8JrBNTwkc
But which native resolution shell we use? This obviously deppends on the screen (platform) you designing for (Smartphones, Tablets, PC, Consoles, Consoles hooked on TV-Screens, …).I like to make a game for PCs. The (probably) most common resouloution is 1920x1080 (16:9 ratio). So I chose 640x360 as native resolution. Its a good trade off between the level of detail for drawing and having a pixel perfect and black bazle free images on common resolutions:
- 640x360 *2 = 1280x720
- … *3 = 1920x1080 (HD)
- … *4 = 2560x1440 (WQHD)
- … *6 = 3840x2160 (4k)
- … *8 = 5120x2880 (5k)
Here is an interesting blog post from D-Pad Studio the makers of Owlboy about the Hi-Bit Era:
As side note: This websites shows you the wolrdwide most common screen resolutions:
So my Unity settings are as follows:
- PPU (pixels per unit) = 16px/unit (my tiles are also 16x16 that means → 1 tile = 1 unit)
- orthographic size = 360px / (2* 16px/unit) = 11.25 unit
For my Sprites I have the following settings:
- PPU = 16
- Filter Mode = Point (no filter)
- Compression = None
2. Smooth (floating point) Camera/Character Movements on a integer Screen
This is the tricky part I think. Because whenever you like to move something smooth in Unity you have floating point operations (lerping, physics calculations, …) so thats a probleme on an integer screen (no half pixels) and I think that my stuttery camera and rippling/warping sprite have to do with this relation.
To analyse this I created a Unity project as test bench where I tried 3 different movements techniques for the player:
- Rigidbody2D.MovePosition(…)
- Rigidbody2D.velocity(…)
- Rigidbody2D.AddForce(…)
And to 2 different „camera follow player“ functions, where each in its core consits out of one of the following functions:
- Camera.transform.position = Vector3.MoveTowards(lastCameraPosition, aimPosition, speed*time
- Camera.transform.position = new Vector3(Player.xposition, Player.yposition
I switched in my test bench project between all of the above mentioned techniques and tried all of them in a built project (anti aliasing and anistropic textures turned off) but no success. Still a stuttery camera and ore warping effects on the sprites.
Regarding this issue I also found another post that addresses this problem:
Compared to games like Stardew Valley, Kingdom New Lands, Eitr or FEZ my camera is really worse. I know not all of these games are made with Unity but how can I achieve such a nice camera with Unity? What did these guys do different? How do you guys achieve a smooth camera? Do you have recommendations? I feel like I don’t make any progress on this topic :(.
I’m thankful for every answer and hint :).
Best regards,
Bredjo