Search Unity

2D Sprite Jitters

Discussion in 'Cinemachine' started by bowserscastle, Apr 3, 2018.

  1. bowserscastle

    bowserscastle

    Joined:
    Jul 9, 2017
    Posts:
    10
    So I've gone through all the threads concerning 2D sprite jittering problems and learned a lot, but none of the solutions seem to fully fix what I'm seeing.

    I'm got a very simple "player object" moving across a Tilemap and a CM Virtual Camera following it. The CMVC has an Ortho size of 16, and all sprites are 32px with 32 PPU. Resolution is locked to 1280x1024. The CMVC is using a framing transposer on the player object. The CM Brain Update Method is set to FixedUpdate(), though I've tried the other two to no avail. Unity 2017.4.0f1, and CM v2.1.10.

    The player object has a Rigidbody 2D on it, Body type: Dynamic, Interpolate: None.
    I'm moving the player object only in FixedUpdate() by adjusting the velocity on the Rigidbody.

    As you can see in this video:
    there's a pretty apparently jitter (when you adjust the scale). I've uploaded a sample project here that demonstrates the problem. I can see the transform position shifting back and forth as the object jitters, but from what I've seen on other threads, that can be a symptom, not a cause.

    Thank you in advance for any pointers!
     
    Last edited: Apr 3, 2018
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    2,725
    I downloaded your project and am able to see the jittering.
    The thing is, it happens even when the CM brain is disabled (and therefore NOT moving the camera).
    You can see it here, I'm just resizing the inspector, player not moving, camera not moving.
    I think it has something to do with the way the sprite is rendered, some kind of pixel rounding.
     

    Attached Files:

    Last edited: Apr 3, 2018
    bowserscastle likes this.
  3. bowserscastle

    bowserscastle

    Joined:
    Jul 9, 2017
    Posts:
    10
    Thank you for taking a look!

    The ortho size in that gif is 8.40625 - does that have something to do with it? I have the resolution locked to 1280x1024, and when you combine that with the ortho size calculation being done in the attached script:
    (Screen.height / 32) / 2

    we get a camera size = 16. When I resize the inspector with the resolution locked, I don't see the jittering. I only see it when moving the player sprite.
     
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    2,725
    OK I figured it out. The problem is that the camera is positioned between pixels, and for some reason the background and foreground sprites are rounding differently. The solution would be to make sure that the camera never moves to a sub-pixel position.

    Here is a little script that post-processes the vcam's position to force it onto pixel boundaries. Add it to your project, then select it as an extension on your vcam:

    Code (CSharp):
    1. using UnityEngine;
    2. using Cinemachine;
    3.  
    4. [ExecuteInEditMode] [SaveDuringPlay] [AddComponentMenu("")] // Hide in menu
    5. public class RoundCameraPos : CinemachineExtension
    6. {
    7.     public float m_PixelsPerUnit = 32;
    8.  
    9.     protected override void PostPipelineStageCallback(
    10.         CinemachineVirtualCameraBase vcam,
    11.         CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
    12.     {
    13.         if (stage == CinemachineCore.Stage.Body)
    14.         {
    15.             Vector3 pos = state.FinalPosition;
    16.             Vector3 pos2 = new Vector3(Round(pos.x), Round(pos.y), pos.z);
    17.             state.PositionCorrection += pos2 - pos;
    18.         }
    19.     }
    20.  
    21.     float Round(float x)
    22.     {
    23.         return Mathf.Round(x * m_PixelsPerUnit) / m_PixelsPerUnit;
    24.     }
    25. }
    26.  
    upload_2018-4-3_11-18-53.png

    Let me know if this fixes the problem.
     
    Kizaqt, Deeeds and bowserscastle like this.
  5. bowserscastle

    bowserscastle

    Joined:
    Jul 9, 2017
    Posts:
    10
    I only "Liked" your post because these forums have no option to "Love" posts.
    Thank you! This script fixed the issue.
     
    Kizaqt and Gregoryl like this.
  6. Kizaqt

    Kizaqt

    Joined:
    Nov 3, 2018
    Posts:
    1
    Another newbie who just had 2 days of frustration on this same issue as a result (I guess) of background tilemap rounding differently to the foreground sprites. Pixel snapping extension script solved my issue.
    Thanks for both working out the problem and solving it Gregory!
     
    bowserscastle and Gregoryl like this.
  7. ShervinM

    ShervinM

    Joined:
    Sep 16, 2017
    Posts:
    18
    Hi guys! I'm running into a similar issue, and wanted to check out your extension @Gregoryl . I'm working on unity 2019.1.10f1, and whenever I try to select an extension, the box remains as "(select)". Have you heard of this happening?
     
  8. ShervinM

    ShervinM

    Joined:
    Sep 16, 2017
    Posts:
    18
    Ah I had some other compiler issues that were getting in the way, apologies for the hasty question. In any case, I managed to get the extension, but it seems like my problem must be something else. Much like @bowserscastle , I've been looking at quite a few posts on achieving pixel perfect games, and 2d jitter, particularly the following post: https://gamedev.stackexchange.com/q...57021?newreg=eeff1626394749b1a5570cad5d2f4a72

    (By the way, is that you @Gregoryl ?).

    I've attached a gif of the issue im observing. Notice how pieces in the environment (the top row of furniture) jiggle up and down when the camera moves. This is particularly evident when the camera makes more up and down motions.

    As from the other link, I've taken precautions and set up my game as follows:
    - I've turned off anti-aliasing and anisotropic textures
    - Specifically targetting 1920 x 1080
    - All sprites have a PPU of 20
    - The camera has an orthographic size of 13.5 (this means that I'm showing 27 units of the world vertically, for 20 sprite texels, which means 540 texels vertically (20 * 27). This is half of 1080, so I should be good on this account right?
    - I'm using a cinemachine vcam that is following my target object (the moving chair in this case).
    - I'm using a framing transposer
    - I'm using a cinamchine confiner
    - The brain is updating on Fixed Update
    - the motion of my target is using rigidbody (non kinematic) by changing the velocity directly. These updates are also done in fixed update.

    Any ideas what might be going on? Any help would be very much appreciated!

     
  9. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    2,725
    It looks to me as though the problem is in the code that places the furniture. The camera is moving nicely (thanks to the position rounding, I presume), but the furniture seems to be suffering from a similar position rounding problem. Can you round its position in the same manner as the camera?
     
    ShervinM likes this.
  10. ShervinM

    ShervinM

    Joined:
    Sep 16, 2017
    Posts:
    18
    Hi Gregoryl!

    Thanks so much for getting back to me!

    I went ahead and made a quick monobehaviour to set the transform.position of the object to the rounded xyz based on the same ppu (just like the camera extension):


    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3.  
    4. public class SnapEnvironment : MonoBehaviour
    5. {
    6.  
    7.     public float m_PixelsPerUnit = 20f;
    8.  
    9.     float Round(float x)
    10.     {
    11.          return Mathf.Round(x * m_PixelsPerUnit) / m_PixelsPerUnit;
    12.     }
    13.  
    14.     private void Update()
    15.     {
    16.          transform.position = new Vector3(Round(transform.position.x),
    17.                                        Round(transform.position.y),
    18.                                        Round(transform.position.z));
    19.     }
    20. }
    I also realized the camera extension you provided wasn't rounding for the z axis (but in my case, the camera is facing towards the x & z plane at a 45 degree angle, and thus moves along the x and z axis, with a fixed y position).

    So I also amended your code to the following:
    Code (CSharp):
    1. ...
    2.             Vector3 pos2 = new Vector3(Round(pos.x), Round(pos.y), Round(pos.z));
    3. ...
    I've attached a gif of the result below. What do you see?

    All of the furniture pieces have the new snap monobehaviour EXCEPT for the right armchair.

    Personally I see less jitter with the armchair to the left, and the top fern, but the others still seem to go crazy.


    Some more information about my scene:
    - The tilemap is sitting on the x & z plane with (interestingly, no jitter here...)
    - Each furniture object is made of a parent root object with nothing but a transform, and then a child object with a sprite renderer with the transform at 45 degrees on the x axis. Both the parent and the child have the snap monobehaviour.
    - As mentioned before, my camera is on a 45 degree angle, facing directly with the 45 degree tilted furniture.


     
  11. yuanxing_cai

    yuanxing_cai

    Unity Technologies

    Joined:
    Sep 26, 2014
    Posts:
    189
    Hi! If you're willing to try out the latest alpha version of Unity 2019.3, then we have a new CM extension in the 2D Pixel Perfect package that enables you to use Cinemachine with the Pixel Perfect Camera. We have code in the Pixel Perfect package that synchronizes the pixel snapping behaviors of the camera and the sprites, which might help in your case.
     
    bowserscastle likes this.