0
\$\begingroup\$

I move a

  • 28x42 Image,

  • in a 11x17 RectTransform

  • in Update,

  • with anti-aliasing on,

  • without compression,

  • with point filtering.

But sadly its visuals aren't smooth, it's flickery, even in a standalone build with 1440p resolution.

enter image description here

I move it like this:

Arrow.anchoredPosition = new Vector2(newX, Arrow.anchoredPosition.y);

I've already tried:

  • Changing the RectTransform's size to 28x42.

  • Turning off anti-aliasing.

  • Changing filtering modes.

  • Moving it in FixedUpdate.

I tried it with a 110x170 and 280x420 RectTransform, but it's still wrong: (110x170 shown below)

enter image description here

Why?

\$\endgroup\$
0
3
\$\begingroup\$

This occurs because you're displaying your sprite at a size on screen such that there's a non-integer ratio between the number of screen pixels it occupies, and the number of source texels in the sprite.

Rippling sprite example

That means that somewhere, some source texels need to be displayed more times than others to fill the space, and which ones get repeated/skipped depends on rounding as your sprite moves, creating a shimmery/rippling effect that rolls over the image as you see here.

Some common ways to fix this, in approximately increasing order of complexity:

  1. Use bilinear filtering on your sprite, instead of nearest neighbour / point filtering.

    Point filtering is great for crisp pixel art, but it requires exacting attention to your display-pixels-per-texel ratio, which might not be what you want here.

    By using bilinear filtering, the GPU is able to blend between adjacent texels when there's a mismatch between the display pixel grid and the source asset, minimizing any apparent ripple or shimmer, especially on high-resolution displays. There can be a slight loss of crispness this way, if your source art isn't sized correctly for your display size, but the degradation is gradual rather than so glaring, so small mismatches are often tolerable enough in this form.

  2. Configure your assets and display settings so that your sprites are always displayed at an integer ratio of display pixels per source texel.

    For some projects, this can be as simple as setting "Constant Pixel Size" on your canvas and keeping your pixels per unit / reference pixels per unit values consistent. The downside is that on low-res displays your UI widgets might look too big/clunky, and on very high-res displays they might look too small to read/use comfortably.

    You can compensate by scaling up your assets by integer factors, to keep them a similar apparent size on all display resolutions you choose to support, within the limits of rounding. Or by swapping to an alternative asset set depending on the resolution to ensure you get pixel-perfect crispness on every supported resolution.

  3. For simple elements like the slider thumb, that need crisp edges at any resolution but lack internal detail, you can ditch conventional sprites and instead render them with signed distance fields, so you can get a pixel-perfect antialiased stroke of controllable thickness over a wide range of display sizes.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.