- Home /
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
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
Unity 2d Standard Assets
Camera from this post
Camera from Unity UFO tutorial
Quality Settings
Experimenting with all Vsync options
Additional Related Research
http://answers.unity3d.com/questions/1373273/camera-movement-causes-2d-sprites-to-shakeglitchji.html
http://answers.unity3d.com/questions/1122629/2d-camera-movement-causes-flickeringjittering-spri.html
http://answers.unity3d.com/questions/615493/how-to-smoothly-move-a-2d-camera-without-ghosting.html
https://forum.unity3d.com/threads/2d-camera-ghosting.239013/
https://www.reddit.com/r/Unity2D/comments/4stgm2/pixelperfect_2d_rendering_in_unity_explained/
The player game object has a "brain" that manages input from an input device and then makes calls to a movement component that actually moves the game object using the rigid body (was trying to keep things separate and re-usable across players, enemies, and other actors).
Snippet from player "brain"
...
protected virtual void Handle$$anonymous$$ovementAndRotation()
{
var direction = GetNormalized$$anonymous$$ovementDirection();
movement.$$anonymous$$oveInDirection(direction.x, direction.y);
var rotation = NormalizeRotationDirection(Input.GetAxisRaw(rotateXAxisName), Input.GetAxisRaw(rotateYAxisName));
if (rotation != Vector2.zero)
movement.RotateInDirection(rotation);
}
private Vector2 GetNormalized$$anonymous$$ovementDirection()
{
return Normalize$$anonymous$$ovementDirection(Input.GetAxisRaw(movementXAxisName), Input.GetAxisRaw(movementYAxisName));
}
private Vector2 Normalize$$anonymous$$ovementDirection(float inputHorizontal, float inputVertical)
{
var movementVectorX = 0f;
var movementVectorY = 0f;
if (inputHorizontal > 0.5f || inputHorizontal < -0.5f)
{
movementVectorX = inputHorizontal;
}
if (inputVertical > 0.5f || inputVertical < -0.5f)
{
movementVectorY = inputVertical;
}
if (inputHorizontal < 0.5f && inputHorizontal > -0.5f)
{
movementVectorX = 0f;
}
if (inputVertical < 0.5f && inputVertical > -0.5f)
{
movementVectorY = 0f;
}
return new Vector2(movementVectorX, movementVectorY);
}
...
Snippet from movement script
...
private void FixedUpdate()
{
myRigidBody.$$anonymous$$ovePosition(currentDestination);
transform.rotation = currentRotation;
}
public virtual Vector3 $$anonymous$$oveInDirection(float inputHorizontal, float inputVertical)
{
var changeInPosition = new Vector2(
current$$anonymous$$oveSpeed * inputHorizontal * Time.deltaTime,
current$$anonymous$$oveSpeed * inputVertical * Time.deltaTime
);
currentDestination = myRigidBody.position + changeInPosition;
return currentDestination;
}
...
You could try changing to a velocity-based movement method. I sometimes find odd things happen to the camera when I'm tracking an object that isn't moving by velocity.
Answer by mr_welsfurd · Jul 25, 2017 at 12:46 AM
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 hope that you can fix that problem soon, that is a big headache when you try to do your first pixel art game. $$anonymous$$an, when you fix that at 100% don't forget make a tutorial! that will be awesome.
why don't you put camera movement in the update ins$$anonymous$$d of fixedupdate? Camera movement are not physics :P
Answer by Reynarz · Jul 19, 2017 at 02:09 AM
Hey man, did you tried with this?https://gist.github.com/pixelrevision/2981863 is the best "pixel perfect cam " script you can get out there!
Thank you for the quick response! Unfortunately, I just tried out the script you linked to and I am still seeing the same problem of blurring\jittering in my game. Are there any settings or other changes that need to be done to make this work correctly?
Given the number of different camera approaches I have tried, I am wondering if maybe the camera isn't actually the root problem.
$$anonymous$$mmm, can you upload a single tile of your floor, in high resolution for see your problem more clear?, the video doesn't help so much :/
Here are a couple of basic sprite sheets I created for the tiles:
https://drive.google.com/open?id=0B1U6uTsxgbi6S2xrQXk2cG$$anonymous$$xX3c
https://drive.google.com/open?id=0B1U6uTsxgbi6QU$$anonymous$$1RTFwZ2JXZEk
I also created a video that is zoomed in a little https://youtu.be/oup6$$anonymous$$Xtw-6k. Here is another zoomed in even more https://youtu.be/_1i1tOb7TVo . Not sure that this helps at all
Answer by ShadyProductions · Jul 20, 2017 at 11:00 AM
You should try turning off anti aliasing, I know it messes with 2d tiles sometimes in my games too.
Thanks for the response. I am pretty sure that I already have anti-aliasing turned off. Here are my Quality Settings. Is there something that I am missing?
I did some research and I don't see any other configurations for anti-aliasing other than the one I have disabled (as shown in the screenshot I provided). I also disabled all of the quality settings,but one just to ensure the game was running with the quality setting I thought it was.
So I don't think anti-aliasing is my problem. Thanks for the suggestions.
Did you disabled the generate mid maps, from your sprite?