2d-pixel-perfect

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

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

在Unity项目中设置、诊断并修复像素完美2D渲染。

⚠️ 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
Component
UnityEngine.Rendering.Universal.PixelPerfectCamera
UnityEngine.U2D.PixelPerfectCamera
PackageBuilt into URP — no extra install
com.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.

Unity中的像素完美渲染并非单一系统——它是两种相互独立且互不兼容的实现,分别对应不同的渲染管线。在编写或诊断任何代码之前,务必先检测所用的管线。
URPBuilt-in
组件
UnityEngine.Rendering.Universal.PixelPerfectCamera
UnityEngine.U2D.PixelPerfectCamera
URP内置 — 无需额外安装
com.unity.2d.pixel-perfect
v6.0.0+
API风格枚举(
gridSnapping
,
cropFrame
布尔值(
pixelSnapping
,
upscaleRT
,
cropFrameX/Y
请勿在URP项目中安装
com.unity.2d.pixel-perfect
包。
→ 务必先调用
DetectPipeline()
(位于
references/pipeline-detection.cs
),再根据检测结果分支处理设置、诊断和修复逻辑。

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

  • 高清2D或高分辨率2D游戏 —— 像素对齐和点过滤会让流畅美术素材的显示效果异常
  • 仅含UI的场景 —— 请改用Canvas Scaler
  • HDRP项目 —— 不支持Pixel Perfect Camera

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.
⚠️ 务必先检测渲染管线 —— URP和内置管线使用的Pixel Perfect Camera组件不同,不可互换。 ⚠️ 过滤模式设为Point是首要修复方案 —— Unity默认使用双线性过滤,这几乎是精灵模糊的根本原因。 ⚠️ 必须禁用抗锯齿 —— 在质量设置和相机设置中都要关闭,AA会主动模糊像素边缘。

Key Principles

核心原则

1. Pipeline Detection & Camera Component Selection

1. 管线检测与相机组件选择

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.
参见本文顶部的双方案对比表。 程序集名称说明:独立的内置管线包安装在
Runtime/
文件夹下,但其asmdef的
"name"
字段为
Unity.2D.PixelPerfect
——没有
Runtime
后缀。 HDRP不受支持——参见「常见问题」中的HDRP替代方案部分。
→ 代码:
references/pipeline-detection.cs
—— 包含
DetectPipeline()
GetPixelPerfectCameraType()
以及迁移不匹配检查。

2. Diagnostic-First Approach

2. 诊断优先原则

Always diagnose before making changes. Report findings, then fix only what is broken.
始终先诊断再修改。先上报发现的问题,再仅修复已确认的故障。

3. Work in the correct scope

3. 在正确的范围内工作

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

精灵导入设置:
  • 所有作用范围内的精灵,过滤模式(Filter Mode)设为
    Point (no filter)
  • 禁用Mip Maps
  • 压缩方式设为
    None
    / 未压缩
  • 场景中所有精灵的PPU保持一致
  • 精灵轴心设为自定义/像素模式——奇数尺寸精灵(例如15×15)的中心轴心会落在7.5px位置,导致0.5px偏移
→ 代码:
references/sprite-settings.cs
—— 包含
GetImporter()
FixSpriteImportSettings()
编辑器对齐设置:
  • 所有轴的网格大小(Grid Size)设为
    1 / assetsPPU
    (例如PPU为16则设为0.0625,PPU为100则设为0.01)
  • 在网格与对齐浮窗中启用网格对齐
  • 对齐现有GameObject:选中后 → 对齐所选对象 → 所有轴
相机设置:
  • 相机投影模式设为正交(Orthographic)
  • 已添加Pixel Perfect Camera组件,且类型与渲染管线匹配
  • allowHDR
    allowMSAA
    allowDynamicResolution
    均设为
    false
  • 场景视图中相机的Gizmo显示两个绿色边界框——实线为可见区域,虚线为参考分辨率
→ 代码:
references/camera-setup-urp.cs
—— 完整的URP相机 + PP Camera配置。 → 代码:
references/camera-setup-builtin.cs
—— 内置管线独立版配置。
项目质量设置:
  • 质量设置中的抗锯齿(Anti-Aliasing)设为0
  • 禁用各向异性过滤(Anisotropic Filtering)

API Reference

API参考

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

完整的属性/方法表、
GridSnapping
CropFrame
枚举值以及推荐配置:
references/api-reference.md
—— 编写或审查相机设置代码时请阅读此文件。
枚举快速摘要:
GridSnapping
None
·
PixelSnapping
(标准模式) ·
UpscaleRenderTexture
(原生低分辨率模式;与后处理和UI文本不兼容)
CropFrame
None
·
Pillarbox
(左右留黑边) ·
Letterbox
(上下留黑边) ·
Windowbox
(四周留黑边,最安全的默认值) ·
StretchFill
(拉伸填充)

Reference Resolution

参考分辨率

Choose before building any assets. Never change after asset production starts.
Reference resolution1080p1440p4K
320 × 18012×
480 × 270~5.3×
640 × 360
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.

在制作任何资源前确定,资源生产开始后切勿修改。
参考分辨率1080p1440p4K
320 × 18012×
480 × 270~5.3×
640 × 360
320×180是最稳妥的通用选择。对于无法整数适配的屏幕(例如1366×768),使用
cropFrame = Windowbox
添加黑边,而非拉伸为非整数缩放比例。

Migration & Compatibility

迁移与兼容性

URP project with the Built-in standalone component

URP项目中使用了内置管线的独立组件

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).
症状
DetectPipeline()
返回URP,但相机上挂载的是
UnityEngine.U2D.PixelPerfectCamera
。症状可能不明显,因为该独立组件包含
ENABLE_URP
条件编译代码。
修复方案
  1. 从包管理器中移除
    com.unity.2d.pixel-perfect
  2. 从每个相机上移除
    UnityEngine.U2D.PixelPerfectCamera
    组件
  3. 添加
    UnityEngine.Rendering.Universal.PixelPerfectCamera
    组件
  4. 重新配置——布尔参数(
    pixelSnapping
    upscaleRT
    cropFrameX/Y
    )需替换为枚举参数(
    gridSnapping
    cropFrame
→ 检测代码:
references/pipeline-detection.cs
(文件底部)。

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

旧版URP命名空间(Unity 2022之前 / URP 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.

症状:引用
UnityEngine.Experimental.Rendering.Universal
时出现编译错误。
修复方案:将
using UnityEngine.Experimental.Rendering.Universal;
替换为
using UnityEngine.Rendering.Universal;
。更新所有程序集限定类型字符串。
[MovedFrom]
特性会自动处理序列化——GameObject上的组件可正常升级。

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
修复方案:将所有作用范围内精灵的过滤模式设为Point,禁用Mip Maps,在质量设置中关闭AA。 → 代码:
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
按顺序排查——诸如负单元格间距或PPU设为31.99之类的变通方法会在相机移动时失效。
#检查项修复方案
1精灵图集(Sprite Atlas)是否关闭了紧密打包(Tight Packing)、内边距(Padding)≥4、且启用了精灵打包器模式?在编辑器设置中启用精灵打包器模式;在图集上设置内边距≥4并关闭紧密打包
2瓦片集纹理和图集是否禁用了Mipmaps?关闭生成Mip Maps
3AA是否为0、相机上的MSAA是否关闭?全局禁用AA
4压缩方式是否为None?使用RGBA 32位未压缩格式
5所有瓦片精灵的像素尺寸是否为偶数?奇数尺寸会导致0.5px网格偏移
6PPU是否等于瓦片像素宽度?(16×16瓦片 → PPU 16)PPU不匹配会导致物理缝隙
7以上检查都通过,但仅在相机移动时出现缝隙?使用PP Camera的像素对齐功能;不要使用
cellGap = -0.01f

Cinemachine conflict

Cinemachine冲突

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)
原因:Cinemachine和Pixel Perfect Camera都会每帧修改正交相机尺寸。
修复方案:在每个虚拟相机(Virtual Camera)的「添加扩展」下拉菜单中添加
CinemachinePixelPerfect
扩展。请勿通过代码中的
AddComponent
添加。
已知限制
  • 虚拟相机之间的混合过渡过程无法做到像素完美
  • UpscaleRenderTexture
    会减少可用的像素完美正交尺寸,可能导致画面构图偏移
  • 目标组+构图转置器(Target Group + Framing Transposer)会导致可见卡顿(暂无修复方案)

Post-processing blur with
upscaleRT

使用
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.
原因:后处理在Pixel Perfect Camera放大渲染纹理之后执行。
简单修复:禁用
upscaleRT
,后处理将以原生屏幕分辨率运行。
高级修复(Unity 6 URP):在
RenderPassEvent2D.AfterRenderingPostProcessing
阶段注入
ScriptableRendererFeature2D
。请使用2D专用基类——3D基类
ScriptableRendererFeature
在URP 2D渲染器中会被静默忽略。

UI text blurry with
upscaleRT

使用
upscaleRT
时UI文本模糊

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)
状态:已知Unity bug,官方拒绝修复(截至Unity 6、2025年仍存在)。
根本原因:(A) Canvas渲染到低分辨率缓冲区,随场景一起被放大。(B) TMP的SDF渐变阈值在低参考分辨率下校准错误。
按可靠性排序的修复方案
  1. 将Canvas设为
    Screen Space - Overlay
    模式——绕过相机,以原生分辨率渲染
  2. 使用专用UI相机,不挂载Pixel Perfect Camera组件,Canvas设为
    Screen Space - Camera
    模式
  3. 仅Unity 6可用:
    字体材质 → 调试设置 → 锐度 = 1
    (可缓解B问题,无法解决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
原因:物理以固定时间步长运行;插值位置会产生小数值,导致每帧对齐到不同的像素。
修复方案
  • 在受物理驱动的精灵上启用
    Rigidbody2D.interpolation = RigidbodyInterpolation2D.Interpolate
  • 设置
    Time.fixedDeltaTime = 1f / 60f
    以匹配目标帧率
  • 将相机跟随逻辑放在
    LateUpdate
    中,而非
    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.
原因:屏幕分辨率不是参考分辨率的整数倍。
修复方案:从上表中选择合适的参考分辨率。当无法整数适配时,使用
cropFrame = Windowbox

Missing URP 2D Renderer

缺少URP 2D渲染器

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+
修复方案
  1. 资产 > 创建 > 渲染 > URP 2D Renderer Data
  2. 将其分配到URP资源的渲染器列表中
  3. 需要
    com.unity.render-pipelines.universal
    12.0及以上版本

HDRP fallback

HDRP替代方案

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.
Pixel Perfect Camera在HDRP中不受支持。
内置管线 / Unity 5.x:使用
RenderTexture
+
Graphics.Blit
,并设置
FilterMode.Point
Unity 6 URP:使用
ScriptableRendererFeature2D
+
ScriptableRenderPass2D
,在
RenderPassEvent2D.AfterRendering
阶段通过
AddRasterRenderPass
注入。注意:
OnRenderImage
Graphics.Blit
与Unity 6的渲染图(render graph)不兼容。