DEV Community

FrameSprite
FrameSprite

Posted on Fully Autonomous

Godot sprite blurry when moving? Diagnose the right layer first

A sprite that is blurry while standing still and a sprite that only shimmers while moving are usually suffering from different bugs. Treating both as “bad filtering” leads to hours of random import changes.

Here is the shortest diagnostic path I use for Godot 4 pixel art.

1. Freeze the scene before touching import settings

Pause the character on a single frame and stop the camera.

  • Soft edges while everything is still usually indicate texture filtering.
  • Sharp while still, unstable while moving usually indicate fractional movement, fractional scale, or camera interpolation.
  • A thin strip from the neighboring pose indicates sprite-sheet grid or atlas bleeding.
  • The whole body jumps between frames indicates inconsistent canvases, pivots, or foot baselines.

Those are four different layers. Change one at a time.

2. Fix stationary blur with Nearest filtering

For pixel art, select the Sprite2D or AnimatedSprite2D node and set:

CanvasItem → Texture → Filter → Nearest

Nearest sampling chooses the closest source pixel rather than blending surrounding pixels. If every pixel-art asset in the project needs the same policy, set the project default instead of editing every node.

Do not assume mipmaps are always wrong. A sprite displayed at native size or an integer enlargement usually does not need them. If the camera shrinks sprites below one source pixel per screen pixel, mipmaps can reduce distant shimmer. Test the real camera scale.

Godot reference: CanvasItem texture filtering

3. If it is sharp while still, inspect motion

Nearest filtering cannot repair fractional transforms.

Log the final rendered position of both the character and Camera2D. Then test four cases:

  1. Character still, camera still
  2. Character moving, camera still
  3. Character still, camera moving
  4. Character and camera moving together

If only cases 3 and 4 fail, the camera path is the likely source. If case 2 fails as well, inspect the character transform and the relationship between physics updates and rendering.

For deliberately crisp pixel art, verify:

  • the final screen position lands on whole pixels;
  • scale is an integer at the intended resolution;
  • character and camera are not being rounded independently in opposing directions;
  • physics-step movement and render interpolation are not fighting each other;
  • the pixel-snap settings match the project's movement model.

Godot's own guide separates jitter and stutter from texture filtering: Fixing jitter, stutter and input lag.

4. Check odd-sized frames and centering

An odd-width or odd-height frame with centered = true can place the visual center between pixels.

That does not mean every pixel sprite must disable centering. Even-sized frames that stay on integer positions can work correctly. But if an odd-sized frame deforms or shimmers, compare these two tests:

  • disable Centered and align with an integer offset;
  • keep centering, but adjust the authored canvas so its anchor lands on a whole pixel.

The goal is a consistent gameplay anchor, not a universal checkbox rule.

5. Diagnose neighboring-frame bleed as atlas math

If the wrong color appears only at a cell boundary, verify the sheet geometry:

sheet width = cell width × columns + gutter × (columns - 1)
sheet height = cell height × rows + gutter × (rows - 1)
Enter fullscreen mode Exit fullscreen mode

The exported pixels and the slicer settings must agree. Adding “padding” only in the editor does not create missing source pixels.

For nearest-filtered, non-mipmapped pixel art, a real 1 px transparent gutter is a reasonable test starting point. Bilinear filtering, downscaling, compression, and mipmaps may require more isolation or alpha-aware edge dilation.

6. Separate frame jitter from transform jitter

Overlay every animation frame on one fixed canvas. Mark one shared foot baseline and one pivot.

Limbs, capes, and weapons can extend. The gameplay anchor should not wander unless the action intentionally translates the character. Cropping each frame to its opaque bounds and then centering it independently is a common way to create apparent bouncing.

If the overlay is stable but the running game is not, return to transforms and the camera. If the overlay itself jumps, repack the source frames before changing engine settings.

A compact symptom table

What you see First place to inspect Likely fix
Soft while still Texture filter Use Nearest for pixel art
Sharp still, shimmers in motion Transform/camera Test integer placement and update timing
Neighboring pose at cell edge Sheet grid/gutters Correct cell math and export real spacing
Character bounces each frame Canvas/pivot Normalize canvas, baseline, and pivot

The important principle is simple: filtering, motion, atlas sampling, and frame alignment are separate systems. Classify the symptom first, then change only the matching layer.

I maintain FrameSprite, and we turned this into a more detailed, engine-focused checklist with failure cases and related sprite-sheet tests:

Godot sprite blurry when moving? Fix blur and jitter

If you are debugging one of these cases now, post which of the four motion tests fails. That usually narrows the problem faster than another round of import changes.

Top comments (0)