2d Top Down Camera Movement Causes Tiles and Other Sprites to Blur\Ghost\Jitter

Summary

I just got started developing with Unity about a month ago. I worked through seveal tutorials and then decided to dive in on my own with a 2d top-down shooter as an example project. Things were going really well until I started noticing that when my camera follows the player game object, everything other than the player blurs\ghosts\jitters. When the camera is not moving everything looks great.

Please see the Example Video to see this in action. The video makes it look a little more subtle, but I feel its still pretty visible. Cranking the quality up to 1080 helps. All of the other details and things I have tried already are documented in the sections below.

Any ideas on what I might be doing wrong? I am not even 100% sure the camera is the root cause, but it seemed like the most obvious place to start looking.

Thank you in advance for your time and input…I have spent days trying to figure this out and have started to run out of ideas. Also, let me know if there is anything additional that would be helpful in understanding the problem further.

Camera Controller Script

Note: This script is attached to the camera game object.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraController : MonoBehaviour 
{
    public GameObject followTarget;

    private Camera attachedCamera;

    public float DefaultOrthographicSize
    {
        get
        {
            return (Screen.height / RenderingConfiguration.PixelsToUnits) / 2;
        }
    }

    void Awake()
    {
        attachedCamera = GetComponent<Camera>();
        attachedCamera.orthographicSize = DefaultOrthographicSize;
    }

    void LateUpdate () 
    {
        if (!followTarget)
            return;

        FollowTarget();
    }

    private void FollowTarget()
    {
        var roundedTargetX = RoundToNearestPixel(followTarget.transform.position.x);
        var roundedTargetY = RoundToNearestPixel(followTarget.transform.position.y);
        var targetPos = new Vector3 (roundedTargetX, roundedTargetY, transform.position.z);
        
        transform.position = targetPos;
    }

    private float RoundToNearestPixel(float unityUnits)  
    {
        // Based on this post https://forum.unity3d.com/threads/solved-2d-sprites-flicker-shake-on-camera-movement.270741/
        var valueInPixels = unityUnits * RenderingConfiguration.PixelsToUnits;
        valueInPixels = Mathf.Round(valueInPixels);
        var roundedUnityUnits = valueInPixels * (1 / RenderingConfiguration.PixelsToUnits);
        return roundedUnityUnits;
    }
}

Project Setup

General

  • Unity 5.6.1
  • Camera Settings
  • Quality Settings
  • Sprite size: 64px
  • Pixel Per Unit: 64px
  • Sprites Rendering:
    • Uses material that has pixelsnap enabled.
    • Filtering = point
    • Mip maps are disabled
  • Test level was created using Tiled and then exported to Unity using Tiled2Unity.
    • unity:scale = 1
    • Pixels Per unit = 64px

Hardware

The monitor that I am testing on isn’t anything special, but it runs at 60hz and I use it for gaming and do not have issues. I have tested other top down 2d games in my steam library on the monitor, such as Moon Hunters, and do not see anything like this issue.

Things that I have tried

Test Setup

  • Running the game in full screen, standalone exe outside the editor, different resolutions, and aspect ratios.
  • Another monitor

Sprites and Tiles

  • Creating a material with pixel snap and making all sprite renders use this instead of the default sprite material.
  • Disabling compression of sprites.
  • Creating a test level using a few tiled sprites instead of the Tiled2Unity export.
  • Using point instead of bilinear filtering
  • Using stock sprites instead of the ones I created. For example, http://kenney.nl/assets/topdown-shooter.

Camera Controller Script

  • Dampening camera movement using Vector3.Lerp and Vector3.SmoothDamp. This actually worsened the situation and I saw some weirdness where the camera’s transform position kept fidgeting after the player stopped moving.
  • Setting orthographic size and rounding camera movement position to nearest pixel as suggested by Shadeless in the post 2D sprites flicker/shake on camera movement and Efficient Tile Map for Platformer
  • Using\modifying existing examples or cameras

Quality Settings

  • Experimenting with all Vsync options

Additional Related Research

https://forum.unity3d.com/threads/2d-camera-ghosting.239013/

https://www.reddit.com/r/Unity2D/comments/4stgm2/pixelperfect_2d_rendering_in_unity_explained/

Hey man, did you tried with this?Script for unity to create a pixel locked orthogonal camera · GitHub
is the best "pixel perfect cam " script you can get out there!

You should try turning off anti aliasing, I know it messes with 2d tiles sometimes in my games too.

After some experimentation I was able to reach an OK solution.

  • First, I found that FixedUpdate was smoother for the camera movements rather than LateUpdate. I am assuming this is because the player movement is being done through the Unity physics engine.
  • Next, I noticed that reducing the amount of single pixel details in the tiles helped mask the appearance of the blurring (but by no means solved the problem). @reynardz had touched on this in one of his posts, but I did not need to mess with the PPU.

However, I still was not very satisfied with the results and did not want to spend anymore time on this problem. So I ended up buying Pro Camera 2d which provided even better results after some fiddling and adding the pixel perfect and camera window extensions. It also has some great features I plan to use in the future like keeping multiple targets in view.

That being said, I still feel like there is still a little too much blurring. I am not sure if this is just me being crazy or what at this point. Anyway, it’s good enough for now. Thanks everyone for the suggestions and ideas.

I don’t know if you have solved this problem, but I can provide my method for you.
Just go to cinemachine, set the body to framing transposer, and then set the x y damping to 0. Basically this problem will be solved. But when you first start walking, there maybe still shaking.
Hope Bro who have better solutions can leave your own solutions here.