SECURITY REVIEW
Not yet assessed
Review the original instructions and requested permissions before installing.
No security review is available for this catalog entry yet.
Set up and fix pixel-perfect 2D rendering for retro-style and pixel art Unity games.
Sets up, diagnoses, and fixes pixel perfect 2D rendering in Unity projects. Use when working on any retro-style or pixel art 2D game.
Review the original instructions and requested permissions before installing.
No security review is available for this catalog entry yet.
How clearly the skill guides your agent, how complete its workflow is, and how you can check the outcome.
No quality assessment is available for this catalog entry yet.
Original instructions from the publisher’s SKILL.md
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.** | | URP | Built-in | |---|---|---| | **Component** | `UnityEngine.Rendering.Universal.PixelPerfectCamera` | `UnityEngine.U2D.PixelPerfectCamera` | | **Package** | Built into URP — no extra install | `com.unity.2d.pixel-perfect` v6.0.0+ | | **API style** | Enums (`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 resolution | 1080p | 1440p | 4K | |---|---|---|---| | 320 × 180 | 6× | 8× | 12× | | 480 × 270 | 4× | ~5.3× | 8× | | 640 × 360 | 3× | 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. | # | Check | Fix | |---|---|---| | 1 | Sprite 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 | | 2 | Mipmaps disabled on tileset textures and atlas? | Disable Generate Mip Maps | | 3 | AA = 0, MSAA off on camera? | Disable AA globally | | 4 | Compression = None? | RGBA 32-bit uncompressed | | 5 | All tile sprites have even pixel dimensions? | Odd dimensions cause 0.5px grid offset | | 6 | PPU = tile pixel width? (16×16 → PPU 16) | PPU mismatch leaves physical gaps | | 7 | Gaps 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.