【もぉん流】Unity × Pixel Perfect : サクッとやったれ!
【もぉん流】やったれ!サクッと Pixel Perfect!
この記事では、Sprite だけでなくライトや UI も含めて Pixel Perfect を実現するための手順を紹介します。環境は Unity + URP(2D Renderer) を想定しています。
下記のような方におすすめです!
- そもそも Pixel Perfect って何!?
- Pixel Perfect を簡単に設定したい!
- ライトや UI までまとめてドット絵に揃えたい!
「Pixel Perfect」という言葉は、ドット絵を描くときの線の技術や、Webページをデザイン通り1px単位で再現する手法、RTAで1px単位で合わせるテクニックなど、いろいろな場面で使われています。本記事で扱うのは、ゲーム画面を描画するときにドット絵の整合性を保つ技術です。
直近の事例として、この記事の内容を実際に使ったゲームがこちら!
死後の世界で魚を釣って寿司を握るブラウザゲーム 『三途の川フィッシング』 です。
このゲームを作る中でやったことの備忘録として、本記事をまとめました。
記事内のスクリーンショットや素材も、このゲームのものを使って説明しています。
0. そもそも Pixel Perfect ってなーに?
ドットがドットのまま映ること!
ひとことで言うと 「ドット絵の 1 ピクセルが、画面上でキレイな正方形のまま表示される状態」 のこと。
通常ドット絵は小さい解像度(たとえば 320×180)で描かれますが、実際にゲームが動作するモニターは 1920×1080 などと大きいため、表示するときに 拡大 が必要になります。
この拡大のやり方がマズいと、様々な見た目の問題が起きてしまいます。
| 症状 | 原因 |
|---|---|
| ドットがにじむ・ぼける | 拡大時にピクセル間の色が補間される |
| ドットのサイズがバラバラになる | 非整数倍(例: 5.3倍)で拡大されて、あるドットは 5px、隣は 6px になる |
| カメラを動かすとガタつく | カメラがサブピクセル(ドットとドットの間)に位置してしまい、フレームごとにドットの並びがブレる |
| ライトや UI だけぼける | Sprite は Pixel Perfect でも、ライトや UI は別の解像度で描画される |
Pixel Perfect のキモは「整数倍」
核心はシンプルに ドット絵を整数倍(2倍、3倍、4倍…)で拡大する こと!
NG: 320 × 3.125 = 1000(中途半端 → ドットのサイズがガタガタ)
OK: 320 × 3 = 960(ぴったり → 全ドット同じサイズ!)
整数倍で拡大することで、すべてのドットが同じサイズの正方形になります。
この記事でやること
Unity の Pixel Perfect Camera だけでも整数倍の表示は実現できます。
しかし、URP の 2D ライティングは 8bit(256段階)を超える高精度な色情報でライトを計算するため、そのまま画面に出すとグラデーションが滑らかすぎて、ドット絵の世界観から浮いてしまうことがあります。
この記事では、8bit の RenderTexture にいったん描画する ことで、ライトの階調をドット絵らしい荒さに落とす方法を採用します。この方法では 2 つのカメラ を使います。
| カメラ | 役割 | 解像度の固定方法 | ポイント |
|---|---|---|---|
| メインカメラ | Sprite やライトなどインゲームの描画 | RenderTexture | 8bit に出力することでライトもドット絵らしい階調になる |
| 最終合成カメラ | RenderTexture と UI を統合して画面に出力 | Pixel Perfect Camera | UI をここで描画することで、クリック・タップ座標がズレない |
設定していく項目はこちら!
- Sprite の Import Settings を整える
- RenderTexture とメインカメラ を構築する
- TextMeshPro のフォントアセットをドット向けにする
- 最終合成カメラ を構築する
やったれ!!
1. Sprite を設定しよう!
まずは素材の設定からです。ここがズレていると、あとで何をやってもドットがにじみます。
Import Settings をこう変えよう
Sprite をクリックして Inspector を開き、以下の項目を確認してください。
| 項目 | 値 | 理由 |
|---|---|---|
| Texture Type | Sprite (2D and UI) | そのままでOK |
| Pixels Per Unit (PPU) | 1マスのドットサイズ | ドットの「1マス」を Unity のワールドに揃えるため |
| Mesh Type | Full Rect | Tight だと端のピクセルが欠けることがあります |
| Filter Mode | Point (no filter) | Bilinear にするとドットがぼけます |
| Max Size | 元画像の解像度以上 | 小さくすると縮小されてしまいます |
| Compression | None | 圧縮するとドットが汚くなります |

PPU は全部揃えよう!
例えば、見下ろし型のゲームで1マスが 16×16 ベースのゲームなら 全 Sprite を PPU = 16 に統一してください。バラバラだと 1 ドットのサイズが素材ごとにズレて、いくら頑張っても揃わなくなります。
1マス という概念が存在しないゲームの場合は、100 で統一しても問題ありません。
Sprite Atlas を使うときも忘れずに
Atlas 側にも Filter Mode: Point と Compression: None の設定があります。
Atlas の設定が元の Sprite の設定を上書きすることがあるので、Atlas 側を優先して確認してください。
2. RenderTexture とメインカメラを構築しよう!
Sprite やライトなど、インゲームの描画を低解像度の RenderTexture に出力する仕組みをつくります。
Step 1: RenderTexture をつくろう
Project ウィンドウで Create → Render Texture を選択し、以下のように設定します。
| 項目 | 値 |
|---|---|
| Size | ゲームの仮想解像度 |
| Anti-aliasing | None (1x) |
| Color Format | R8G8B8A8_UNorm |
| Depth Stencil Format | None(2D ならだいたい不要) |
| Wrap Mode | Clamp |
| Filter Mode | Point (no filter) ← ここは絶対 Point です! |
この RenderTexture のサイズが、ゲーム世界の「ドット解像度」になります。

Step 2: メインカメラを設定しよう
メインカメラの Inspector で以下を設定します。

- Output Texture → 作った RenderTexture をセット
- Pixel Perfect Camera → つけません!
メインカメラには Pixel Perfect Camera は不要です。
RenderTexture のサイズ自体がドット解像度なので、そこに描画するだけで自然とドット解像度になります。
orthographicSize は RenderTexture の高さと PPU から計算して手動で設定してください。
orthographicSize = RenderTexture の高さ ÷ PPU ÷ 2
例: 高さ 180、PPU 16 の場合 → 180 ÷ 16 ÷ 2 = 5.625
2D ライトについて
URP の Light2D(Global Light、Point Light、Freeform Light など)は、
メインカメラに映っていれば RenderTexture にそのまま描画されます。
URP の 2D ライティングは 8bit より高精度に計算されるため、直接画面に出すとグラデーションが滑らかすぎてドット絵感が薄れます。R8G8B8A8_UNorm の RenderTexture を経由する ことで、計算結果が 8bit(256段階)に丸められ、ドット絵らしいカクカクした階調のライトになります。

※どちらもPixel Perfectではあるものの、ライティングの計算が高精度すぎることでドット絵に見えずらい
3. TextMeshPro のフォントアセットを設定しよう!
ドットフォントを TextMeshPro で使うと、デフォルトでは SDF レンダリングによってぼけてしまいます。ビットマップフォントとして生成 することで解決しましょう!
フォントアセットをつくろう
Window → TextMeshPro → Font Asset Creator を開いて、以下のように設定します。
| 項目 | 設定 | ポイント |
|---|---|---|
| Source Font File | 使いたいドットフォント(.ttf / .otf) | — |
| Sampling Point Size | フォントの原寸サイズ(例: 8, 12, 16) |
ドットフォントがデザインされたサイズを指定します |
| Padding | ↑と同様の値 | 小さすぎる値だと、文字が綺麗に描画されません |
| Atlas Resolution | グリフ数に合わせて調整(例: 256 × 256) |
— |
| Character Set | 必要な文字セットを選択 | 日本語を含める場合は Custom Characters でまとめて指定したり、生成後にModeをDynamicにします |
| Render Mode | RASTER_HINTED または RASTER | ★ ここが一番大事! SDF 系を選ぶとドットがぼけます |
設定できたら Generate Font Atlas → Save でアセットを保存してください。


TMP コンポーネントの設定
Font Asset : 作ったアセット
Font Size : Sampling Point Size の整数倍(等倍 / 2倍 / 3倍 ...)
Font Size を 1.5 倍などの非整数倍にすると、リサンプリングが走ってドットが崩れます。必ず整数倍 にしてください。

4. 最終合成カメラを構築しよう!
メインカメラの RenderTexture と UI を統合して、画面に出力するカメラをつくります。
全体の構成
┌─────────────────────────────────────────────────
│ 最終合成カメラ
│ Pixel Perfect Camera (Upscale RT + Window Box)
│ ┌───────────────────────────────────────────────
│ │ Canvas (Screen Space - Camera)
│ │ ┌────────────────────────────────────────────
│ │ │ RawImage
│ │ │ (RenderTexture を表示)
│ │ └────────────────────────────────────────────
│ │ ┌────────────────────────────────────────────
│ │ │ UI 要素
│ │ │ (HP バー、メニュー等)
│ │ └────────────────────────────────────────────
│ └───────────────────────────────────────────────
└─────────────────────────────────────────────────
↑ 出力解像度に収まる最大の整数倍に自動で拡大
┌─────────────────────────────────────────────────
│ 低解像度 RenderTexture (例: 320×180)
│ ┌────────┐ ┌───────┐
│ │ Sprite │ │ Light │
│ └────────┘ └───────┘
│ ↑ ドット解像度で描画!
│ メインカメラ (出力先: RT)
└─────────────────────────────────────────────────
Step 1: 最終合成カメラをつくろう
新しいカメラを作成し、Pixel Perfect Camera コンポーネントを追加します。
カメラの設定:
- Clear Flags: Solid Color(黒)
- Culling Mask: UI レイヤーのみ(ゲームオブジェクトは映さない)
Pixel Perfect Camera の設定:
| 項目 | 設定 | 解説 |
|---|---|---|
| Assets Pixels Per Unit | Sprite の PPU と同じ値 | — |
| Reference Resolution | RenderTexture と同じサイズ | — |
| Crop Frame | Window Box | 整数倍に収まらない領域は、描画せず真っ黒になります |
| Grid Snapping | Upscale Render Texture | 整数倍での拡大を有効にします |
Window Box を選ぶと、画面サイズがドット解像度の整数倍にぴったり合わない場合に、
余った部分が黒い帯(ピラーボックス / レターボックス)で埋められます。

Step 2: Canvas と RawImage を設定しよう
最終出力用の Canvas を作成し、RenderTexture を画面に映す仕組みをつくります。
Canvas の設定:
| 項目 | 値 |
|---|---|
| Render Mode | Screen Space - Camera |
| Pixel Perfect | TRUE |
| Render Camera | 最終合成カメラ |
Canvas Scaler の設定:
| 項目 | 値 |
|---|---|
| UI Scale Mode | Scale With Screen Size |
| Reference Resolution | ドット絵の解像度 |
| Screen Match Mode | Expand |
| Reference Pixels Per Unit | SpriteのPPUと揃える |

RawImage の設定:
Canvas の子要素として RawImage を作成します。
| 項目 | 値 |
|---|---|
| Texture | メインカメラの RenderTexture |
| Rect Transform | 中央揃え、サイズは RenderTexture と同じ |
| Raycast Target | OFF |
これで、メインカメラが描画したドット絵が、最終合成カメラを通して整数倍で画面に表示されます!

Step 3: UI を配置しよう
UI はこの RawImage より下側に配置します。Screen Space - Camera の Canvas 以下であるため ピクセルパーフェクトな UI & 正確なクリック判定 が両立できます!
| 項目 | 値 |
|---|---|
| Rect Transform | 中央揃え、サイズは RenderTexture と同じ |

まとめ
| やること | ポイント |
|---|---|
| 0. Pixel Perfect を知る | 整数倍で拡大して、全ドットを同じサイズに揃える |
| 1. Sprite を設定 | PPU 統一、Point Filter、圧縮なし |
| 2. RenderTexture とメインカメラを構築 | 8bit の RT にインゲーム(Sprite・ライト)を描画。ライトの階調もドット絵らしくなる |
| 3. TMP フォントアセットを設定 | Render Mode を RASTER にする、Font Size は整数倍のみ |
| 4. 最終合成カメラを構築 | Pixel Perfect Camera + Canvas + RawImage + UI で画面に出力 |
Pixel Perfect の基本は 「すべての描画を同じドット解像度に通す」 こと。
メインカメラの RenderTexture でインゲームを、最終合成カメラの Pixel Perfect Camera で UI を、それぞれきっちり整数倍に揃えれば、全部まとめてドットの世界に収まります!
💡 Tips: ポストプロセスの使い分け
この構成ではカメラが 2 つあるため、どちらのカメラでポストプロセスを有効にするか で効果の範囲が変わります。
メインカメラで ON にした場合
ポストプロセスの効果は RenderTexture に描画されるゲーム画面(Sprite・ライト)にだけ かかります。UI には影響しません。
例えば「ゲーム画面だけヴィネットを暗くしたいけど、UI はくっきり見せたい」といったケースに向いています。
最終合成カメラで ON にした場合
ポストプロセスの効果は UI を含む画面全体 にかかります。
例えば「メニューを開いたときに画面全体をぼかしたい」といったケースに向いています。
2 重がけに注意!
両方のカメラで同じ効果を ON にすると 2 重にかかってしまいます。
例えば Bloom を両方で有効にすると、想定以上に光が飛んでしまいます。
「このカメラは何を描画しているのか」を常に意識して、効果の配置先を決めてください。
Volume の分離方法:
- Culling Mask: 各カメラが描画するレイヤーを分ける
- Volume Mask(URP): カメラごとに影響を受ける Volume を指定できます
これらを使って、メインカメラ用の Volume と最終合成カメラ用の Volume をきっちり分離しておくと、意図しない 2 重がけを防げます。
💡 Tips: Transform の Scale と Rotation は使わない!
Pixel Perfect な見た目を維持するために、Sprite の Scale や Rotation は原則さわらない ようにしましょう。
Rotation(回転)は確実にジャギる
ドット絵を 45° や 30° など中途半端な角度で回転させると、ピクセルの並びが崩れて 必ずジャギ(ギザギザ)が発生します。これはどんな設定をしても避けられません。
回転したドット絵が必要な場合は、回転した状態のスプライトを別途用意する のが確実です。
Scale(拡縮)もジャギりやすい
単純な矩形(四角いUI枠など)であれば目立たないこともありますが、
複雑な形状のスプライトを拡縮すると 高確率でドットの並びが崩れます。
拡大・縮小が必要な場合も、サイズ別のスプライトを用意する のがおすすめです。
参考になれば、Like❤️お願いします!
Discussion