PluginBench
Skill
Pass
Audit score 90

2d-pixel-perfect

unity-technologies/skills

Set up, diagnose, and fix pixel-perfect 2D rendering in Unity with PixelPerfectCamera for retro and pixel-art games.

What is 2d-pixel-perfect?

Configures and troubleshoots pixel-perfect 2D rendering in Unity projects using PixelPerfectCamera. Use this when retro-style or pixel-art games appear blurry, jittery, or misaligned. Not suitable for HD 2D games or high-resolution artwork.

  • Detects render pipeline (URP vs Built-in) and selects the correct PixelPerfectCamera component
  • Diagnoses sprite import settings, camera configuration, and project quality settings for pixel-perfect rendering
  • Fixes common issues: blurry sprites, tilemap gaps, anti-aliasing conflicts, and Cinemachine integration
  • Configures grid snapping, crop frame modes, and reference resolution for consistent pixel alignment
  • Handles migration between incompatible URP and Built-in implementations
  • Provides reference resolution tables and optimal settings for different screen sizes

How to install 2d-pixel-perfect

npx skills add https://github.com/unity-technologies/skills --skill 2d-pixel-perfect
Prerequisites
  • Unity project with URP or Built-in render pipeline (HDRP not supported)
  • For Built-in: com.unity.2d.pixel-perfect package v6.0.0 or later installed
  • Orthographic camera in your scene
Claude Code
Cursor
Windsurf
Cline

How to use 2d-pixel-perfect

  1. 1.Run DetectPipeline() to identify whether your project uses URP or Built-in render pipeline
  2. 2.Execute the diagnostic checklist: verify sprite Filter Mode is set to Point, disable Mip Maps, check camera is orthographic, and confirm Anti-Aliasing is disabled in Quality Settings
  3. 3.Review the diagnostic report to identify which settings are misconfigured
  4. 4.Apply fixes using the provided reference code: sprite-settings.cs for import settings, camera-setup-urp.cs or camera-setup-builtin.cs for camera configuration
  5. 5.Set Grid Size in the editor snap settings to 1 / assetsPPU and enable Grid Snapping
  6. 6.Test the scene to confirm sprites are sharp and aligned without jitter or gaps

Use cases

Good for
  • Developing a retro-style 2D game with pixel art that appears blurry or misaligned on screen
  • Setting up a new pixel-art project with correct sprite import and camera settings from the start
  • Troubleshooting tilemap rendering with gaps between tiles during camera movement
  • Integrating Cinemachine with pixel-perfect rendering without losing alignment
  • Migrating a project from Built-in to URP while preserving pixel-perfect camera setup
Who it's for
  • 2D game developers working with pixel art or retro-style graphics
  • Unity developers using URP or Built-in render pipelines
  • Game developers integrating Cinemachine with pixel-perfect cameras
  • Technical artists setting up sprite atlases and tilemaps

2d-pixel-perfect FAQ

What is the difference between URP and Built-in PixelPerfectCamera?

URP uses UnityEngine.Rendering.Universal.PixelPerfectCamera with enum-based properties (gridSnapping, cropFrame), while Built-in uses UnityEngine.U2D.PixelPerfectCamera with boolean properties (pixelSnapping, upscaleRT). They are incompatible — always detect the pipeline first.

Why do my sprites look blurry even with pixel-perfect rendering enabled?

The most common cause is Filter Mode set to Bilinear instead of Point. Also disable Mip Maps on sprites, set Anti-Aliasing to 0 in Quality Settings, and disable MSAA on the camera.

How do I fix gaps appearing between tilemap tiles?

Work through the checklist in order: enable Sprite Packer Mode with Padding ≥ 4, disable Mip Maps, set Anti-Aliasing to 0, use RGBA 32-bit uncompressed textures, ensure tiles have even pixel dimensions, and set PPU equal to tile pixel width. Use pixel snapping, not negative cellGap values.

Can I use Cinemachine with pixel-perfect rendering?

Yes, but you must add the CinemachinePixelPerfect extension via the Add Extension dropdown on each Virtual Camera. Do not add it via AddComponent. Note that camera blends between virtual cameras are not pixel-perfect during transitions.

What reference resolution should I choose for my pixel-art game?

320×180 is the safest general choice. For 1080p it scales 6×, for 1440p it scales 8×, and for 4K it scales 12×. For screens with no integer fit, use cropFrame = Windowbox to add black bars instead of stretching.

Full instructions (SKILL.md)

Source of truth, from unity-technologies/skills.


name: 2d-pixel-perfect description: Sets up, diagnoses, and fixes pixel perfect 2D rendering with PixelPerfectCamera in URP or Built-in. Use when a retro-style or pixel art 2D game looks blurry, jittery, or misaligned. Not for HD 2D or high-resolution art.

Set up, diagnose, and fix pixel perfect 2D rendering in Unity projects.


⚠ There Are Two Completely Separate Implementations

Pixel perfect rendering in Unity is not one system — it is two separate, incompatible implementations, one per render pipeline. Always detect the pipeline before writing or diagnosing any code.

URPBuilt-in
ComponentUnityEngine.Rendering.Universal.PixelPerfectCameraUnityEngine.U2D.PixelPerfectCamera
PackageBuilt into URP — no extra installcom.unity.2d.pixel-perfect v6.0.0+
API styleEnums (gridSnapping, cropFrame)Booleans (pixelSnapping, upscaleRT, cropFrameX/Y)

Do not install com.unity.2d.pixel-perfect in a URP project.

→ Always call DetectPipeline() first (references/pipeline-detection.cs), then branch your setup, diagnostics, and fixes based on the result.


When NOT to use this skill

  • HD 2D or high-resolution 2D games — pixel snapping and point filtering will make smooth art look wrong
  • UI-only scenes — use Canvas Scaler instead
  • HDRP projects — Pixel Perfect Camera is not supported

Critical Reminders

⚠ Detect the render pipeline first — URP and Built-in use different Pixel Perfect Camera components that are not interchangeable. ⚠ Filter Mode = Point is the #1 fix — bilinear filtering is Unity's default and is almost always the cause of blurry sprites. ⚠ Anti-Aliasing must be disabled — in Quality Settings and on the camera. AA actively blurs pixel edges.

Key Principles

1. Pipeline Detection & Camera Component Selection

See the two-path comparison table at the top of this file. Assembly name note: the standalone Built-in package installs into a Runtime/ folder, but the asmdef "name" field is Unity.2D.PixelPerfect — no Runtime suffix. HDRP is unsupported — see the HDRP fallback section under Common Issues.

→ Code: references/pipeline-detection.cs — DetectPipeline(), GetPixelPerfectCameraType(), and migration mismatch check.

2. Diagnostic-First Approach

Always diagnose before making changes. Report findings, then fix only what is broken.

3. Work in the correct scope

Default to scene scope. Scan project-wide only when the user explicitly requests it.


Diagnostic Checklist

Sprite import settings:

  • Filter Mode = Point (no filter) on all in-scope sprites
  • Mip Maps = disabled
  • Compression = None / Uncompressed
  • PPU consistent across all sprites in scene
  • Sprite pivots set to Custom / Pixels mode — a center pivot on an odd-dimension sprite (e.g. 15×15) lands at 7.5px, causing 0.5px misalignment

→ Code: references/sprite-settings.cs — GetImporter() and FixSpriteImportSettings().

Editor snap settings:

  • Grid Size = 1 / assetsPPU on all axes (e.g. PPU 16 → 0.0625, PPU 100 → 0.01)
  • Grid Snapping enabled in the Grid and Snap overlay
  • To snap existing GameObjects: select them → Align Selected → All Axes

Camera setup:

  • Camera projection = Orthographic
  • Pixel Perfect Camera component present and correct type for pipeline
  • allowHDR, allowMSAA, allowDynamicResolution all false
  • Scene view shows two green bounding boxes on the camera gizmo — solid = visible area, dotted = reference resolution

→ Code: references/camera-setup-urp.cs — full URP camera + PP Camera configuration. → Code: references/camera-setup-builtin.cs — Built-in standalone configuration.

Project quality settings:

  • Anti-Aliasing = 0 in Quality Settings
  • Anisotropic Filtering = Disabled

API Reference

Full property/method tables, GridSnapping and CropFrame enum values, and recommended configurations: → references/api-reference.md — read this when writing or reviewing camera setup code.

Quick enum summary:

GridSnapping: None · PixelSnapping (standard) · UpscaleRenderTexture (authentic low-res; incompatible with post-processing and UI text)

CropFrame: None · Pillarbox · Letterbox · Windowbox (safest default) · StretchFill


Reference Resolution

Choose before building any assets. Never change after asset production starts.

Reference resolution1080p1440p4K
320 × 1806×8×12×
480 × 2704×~5.3×8×
640 × 3603×4×6×

320×180 is the safest general choice. For screens with no integer fit (e.g. 1366×768), use cropFrame = Windowbox to add black bars rather than stretching to a fractional scale.


Migration & Compatibility

URP project with the Built-in standalone component

Symptom: DetectPipeline() returns URP but camera has UnityEngine.U2D.PixelPerfectCamera. Symptoms are subtle because the standalone component has ENABLE_URP conditional code.

Fix:

  1. Remove com.unity.2d.pixel-perfect from Package Manager
  2. Remove UnityEngine.U2D.PixelPerfectCamera from each camera
  3. Add UnityEngine.Rendering.Universal.PixelPerfectCamera
  4. Reconfigure — booleans (pixelSnapping, upscaleRT, cropFrameX/Y) become enums (gridSnapping, cropFrame)

→ Detection code: references/pipeline-detection.cs (bottom of file).

Old URP namespace (pre-Unity 2022 / URP pre-13.x)

Symptom: Compiler errors referencing UnityEngine.Experimental.Rendering.Universal.

Fix: Replace using UnityEngine.Experimental.Rendering.Universal; with using UnityEngine.Rendering.Universal;. Update any assembly-qualified type strings. The [MovedFrom] attribute handles serialization automatically — components on GameObjects survive the upgrade.


Common Issues & Solutions

Blurry sprites

Fix: Set Filter Mode to Point on all in-scope sprites, disable Mip Maps, disable AA in Quality Settings. → Code: references/sprite-settings.cs

Tilemap gaps between tiles

Work through in order — workarounds like negative cell gap or PPU = 31.99 break when the camera moves.

#CheckFix
1Sprite Atlas with Tight Packing off, Padding ≥ 4, Sprite Packer Mode enabled?Enable Sprite Packer Mode in Editor settings; on the atlas set Padding ≥ 4 and turn Tight Packing off
2Mipmaps disabled on tileset textures and atlas?Disable Generate Mip Maps
3AA = 0, MSAA off on camera?Disable AA globally
4Compression = None?RGBA 32-bit uncompressed
5All tile sprites have even pixel dimensions?Odd dimensions cause 0.5px grid offset
6PPU = tile pixel width? (16×16 → PPU 16)PPU mismatch leaves physical gaps
7Gaps only during camera movement after all above pass?Use PP Camera pixel snapping; do not use cellGap = -0.01f

Cinemachine conflict

Cause: Both Cinemachine and the Pixel Perfect Camera write to orthographic size every frame.

Fix: Add CinemachinePixelPerfect extension via the Add Extension dropdown on each Virtual Camera. Do not add it via AddComponent in code.

Known limitations:

  • Camera blends between virtual cameras are not pixel-perfect during transitions
  • UpscaleRenderTexture reduces valid pixel-perfect ortho sizes, which may cause framing to deviate
  • Target Group + Framing Transposer causes visible choppiness (no fix available)

Post-processing blur with upscaleRT

Cause: Post-processing runs after the PP Camera upscales the render texture.

Simple fix: Disable upscaleRT. Post-processing then runs at native screen resolution.

Advanced fix (Unity 6 URP): Inject a ScriptableRendererFeature2D at RenderPassEvent2D.AfterRenderingPostProcessing. Use 2D-specific base classes — ScriptableRendererFeature (3D base class) is silently ignored in a URP 2D renderer.

UI text blurry with upscaleRT

Status: Known Unity bug, declined to fix (still present Unity 6, 2025).

Root causes: (A) Canvas renders into the low-res buffer and is upscaled with the scene. (B) TMP's SDF gradient threshold is miscalibrated at low reference resolutions.

Fixes in order of reliability:

  1. Screen Space - Overlay on Canvas — bypasses the camera, renders at native resolution
  2. Dedicated UI camera with no PP Camera component, Screen Space - Camera mode
  3. Unity 6 only: Font Material → Debug Settings → Sharpness = 1 (mitigates B, not A)

Physics / render desync (micro-stutter)

Cause: Physics runs at a fixed timestep; interpolated positions produce fractional values that snap to different pixels each frame.

Fix:

  • Enable Rigidbody2D.interpolation = RigidbodyInterpolation2D.Interpolate on physics-driven sprites
  • Set Time.fixedDeltaTime = 1f / 60f to match target frame rate
  • Keep camera tracking in LateUpdate, not FixedUpdate

Non-integer scaling / pixel decimation

Cause: Screen resolution is not a clean integer multiple of the reference resolution.

Fix: Choose a reference resolution from the table above. Use cropFrame = Windowbox when no integer fit exists.

Missing URP 2D Renderer

Fix:

  1. Assets > Create > Rendering > URP 2D Renderer Data
  2. Assign it to your URP Asset under Renderer List
  3. Requires com.unity.render-pipelines.universal 12.0+

HDRP fallback

Pixel Perfect Camera is unsupported in HDRP.

Built-in / Unity 5.x: Use RenderTexture + Graphics.Blit with FilterMode.Point.

Unity 6 URP: Use ScriptableRendererFeature2D + ScriptableRenderPass2D injected at RenderPassEvent2D.AfterRendering with AddRasterRenderPass. Note: OnRenderImage and Graphics.Blit are incompatible with Unity 6's render graph.