2D Pixel Perfect Camera Movement Causes Jitters

Hello, I’m struggling to get smooth camera movement in my top down game. As I said I’m using the pixel perfect camera package, and I don’t know why this camera script seems to cause jitters. My character movement is completely fine if the camera is static, but once I turn on the follow script the jittering starts. I followed this guide for the camera script (minus the camera shake). I have tried locking the camera position to the nearest pixel (my game is 16 ppu so locked to nearest multiple of 0.0625) but it didn’t help anything. Even after turning off the pixel perfect camera, I feel like there is still a slight jitter (may be placebo, but I don’t think so). Full code below, any advice?

public class cameraFollow : MonoBehaviour
{
    private Vector3 target;
    private Vector3 mousePos;
    public Vector3 refVel;
    public Transform player;
    public float lerpSpeed;
    private float zStart;
    public float cameraDist;

    // Start is called before the first frame update
    void Start()
    {
        target = player.position;
        zStart = transform.position.z; //keep distance from sprites locked, no zooming only panning.
    }

    void Update()
    {
        mousePos = CaptureMousePos();
        target = UpdateTargetPos();
        UpdateCameraPosition();
    }

    Vector3 CaptureMousePos()
    {
        Vector2 ret = Camera.main.ScreenToViewportPoint(Input.mousePosition); //raw mouse pos
        ret *= 2;
        ret -= Vector2.one; //0,0 = middle of screen
        float max = 0.9f;
        if (Mathf.Abs(ret.x) > max || Mathf.Abs(ret.y) > max)
        {
            ret = ret.normalized; //helps smooth near edges of screen. you won't get a longer view if you put your mouse in the corner
        }
        return ret;
    }

    Vector3 UpdateTargetPos()
    {
        Vector3 mouseOffset = mousePos * cameraDist; //mult mouse vector by distance scalar
        Vector3 ret = player.position + mouseOffset; //find position as it relates to the player
        ret.z = zStart; //make sure camera stays at same Z coord
        return ret;
    }

    void UpdateCameraPosition()
    {
        Vector3 tempPos;
        tempPos = Vector3.SmoothDamp(transform.position, target, ref refVel, lerpSpeed);
        transform.position = tempPos; //update the position
    }

}

bump

I’d like an expert opinion on the matter because I’m just starting to learn Unity. But …

By doing a bit of reverse engineering to the Pixel Perfect Camera script I found out that it tries to move the camera even if just a tiny bit so it is always fighting for the camera position. I tried using the Pixel Perfect Cinemachine extension but didn’t do much to fix it, in fact the jittering was still there.

What I ended up doing (I know isn’t the best or should be the final answer) was taking the code that calculates the ortho size for the camera and making my own script to update it. Hopefully this also fixes your issue and someone with more experience than me can truly figure out (and fix) whatever is going on.

Below is the script I created if you are interested in trying it yourself.

using System;
using UnityEngine;


[DisallowMultipleComponent]
[RequireComponent(typeof(Camera))]
public class PixelPerfectCamera : MonoBehaviour
{

    [SerializeField]
    private int assetsPixelsPerUnit = 100;
    [SerializeField]
    private Vector2Int referenceResolution = new Vector2Int(320, 180);

    private Camera _camera;

    private void Awake()
    {
        _camera = GetComponent<Camera>();
    }

    private void OnEnable()
    {
        UpdatePixelPerfectCameraSize();
    }

    private void LateUpdate()
    {
        UpdatePixelPerfectCameraSize();
    }

    private void UpdatePixelPerfectCameraSize()
    {
        if (!_camera || !_camera.orthographic)
            return;

        var cameraTexture = _camera.targetTexture;
        var screenWidth = cameraTexture ? cameraTexture.width : Screen.width;
        var screenHeight = cameraTexture ? cameraTexture.height : Screen.height;

        var verticalZoom = screenHeight / referenceResolution.y;
        var horizontalZoom = screenWidth / referenceResolution.x;
        var zoom = Math.Max(1, Math.Min(verticalZoom, horizontalZoom));

        var cameraOrthoSize = screenHeight * .5f / (zoom * assetsPixelsPerUnit);
        _camera.orthographicSize = cameraOrthoSize;
    }

}

I don’t know if this is true, everything I’ve heard about the pixel perfect camera makes it clear that it’s not changing the Transform position of anything. Unfortunately your script didn’t help, but thank you. It makes me a bit more hopeful for my case that there are other people with this problem.

I have actually fixed my problem. Basically, I was only locking my players position and my damped position to pixels. What fixed it was locking both my undamped target position AND the damped final position to pixels, along with the player. Hope this fixes your problem!