1
votes

I've been struggling with an issue for quite some time now and have all but run out of ideas.

enter image description here

I'm using a Cinemachine Virtual Camera in a 2D project to follow around a target. The ground / background is a Unity Tilemap GameObject. As you can see in this gif, when following around the player (a 24x24 sprite), the background tiles seem to warp a bit. I've tried to script all types of solutions to adjust the Virtual Camera transform position and hopefully snap/move it "correctly" to no avail. I don't even know for sure that the source of the issue is with the camera setup. I'm running out of solutions to something that seems like a pretty straightforward and very common scenario. I've created a sample project illustrating the issue which can be downloaded here.

Using Unity 2017.3.1f1 Personal. The background sprites are 32x32, with a PPU of 32. No compression, Point (no filter), rendered using a material with Shader: Sprites/Default, and Pixel snap.

Cinemachine Virtual Cam is set to Ortho lens size 16, Body: Framing Transposer with default settings.

Thank you so much for any suggestions or tips!!!

It feels similar to what's being described here with sub-pixel movement but I don't know for sure, and the solution in that blog post seems like it should be unnecessary (but again - maybe not).

I've created camera scripts and attached them to the virtual camera as follows:

float maxPixelHeight = 32;
CinemachineVirtualCamera vcam;

public void Awake()
    {
        float scale = Screen.height / maxPixelHeight;
        float orthographicSize = (Screen.height / scale) / 2f;
        vcam = GetComponent<CinemachineVirtualCamera>();
        vcam.m_Lens.OrthographicSize = orthographicSize;
}

    public void Update()
    {
        Vector3 tempPos = vcam.transform.position;
      Vector3 newPos = new Vector3(Mathf.RoundToInt(tempPos.x), Mathf.RoundToInt(tempPos.y), Mathf.RoundToInt(tempPos.z));
        vcam.transform.position = tempPos;
    }

I've also tried:

public void Update()
    {
        Vector3 tempPos = vcam.transform.position;
Vector3 newPos = new Vector3((float)System.Math.Round((decimal)tempPos.x, 2) , (float)System.Math.Round((decimal)tempPos.y, 2), (float)System.Math.Round((decimal)tempPos.z, 2));
        vcam.transform.position = newPos;
    }

and something like:

public void Update()
    {
        Vector3 tempPos = vcam.transform.position;
        vcam.transform.position = new Vector3(RoundToNearestPixel(tempPos.x), RoundToNearestPixel(tempPos.y), RoundToNearestPixel(tempPos.z));    
    }

    public float RoundToNearestPixel(float unityUnits)
    {
        float valueInPixels = unityUnits * maxPixelHeight;
        valueInPixels = Mathf.Round(valueInPixels);
        float roundedUnityUnits = valueInPixels * (1 / maxPixelHeight);
        return roundedUnityUnits;
    }
1

1 Answers

1
votes

I cross-posted this question to https://gamedev.stackexchange.com and someone responded with a great answer:

https://gamedev.stackexchange.com/a/157021/11212