Godotでドット絵がぼやける? くっきり保つインポート設定
Godotでドット絵がぼやける原因は、たいていリニアフィルター、非可逆・ミップマップ付きのインポート、整数でない拡大です。StudioのGodotバンドルはファイルに入る部分を直し、残りのプロジェクト設定は下にまとめました。
Godot 4でドット絵がぼやける原因は4つのどれかです。ノードがプロジェクト既定のLinearフィルターで描かれている、テクスチャがミップマップや非可逆・VRAM圧縮で取り込まれた、ウィンドウがゲームを小数倍に引き伸ばしている、スプライトやCamera2Dが画面のピクセルの間にある。まず止まった画面、次に動いている画面を確認します。NerulioのGodot 4バンドルはファイル側(Nearestのシーン、可逆・ミップマップなしの.png.import)を直し、引き伸ばし・スナップ・カメラは自分で変えるプロジェクト設定です。

- Godot 4検証済み· Godot 4.7.2
- Unity 6検証済み· Unity 6000.5.3f1
- Phaser 3 / 4検証済み· Phaser 3.90 + 4.2
- PixiJS 8検証済み· PixiJS 8.21
- Aseprite JSON検証済み· Phaser load.aseprite · PixiJS 8.21
- .aseprite検証済み· Aseprite 1.3.18
- Spine / libGDX検証済み· spine-canvas 4.2
- Starling / Sparrow XML検証済み· Phaser 4.2
- LÖVE検証済み· LÖVE 11.5
- Defoldビルド確認· Defold bob.jar 1.13.1
- GameMaker未検証
- CSS sprites検証済み· Chromium
- GIF / APNGデコード確認· Pillow
ぼけは4種類、直す場所も4つ
フィルター。Godot 4.0からフィルターは取り込んだテクスチャではなくノードの属性です(CanvasItem › Texture › Filter)。継承(Inherit)のままのノードは親のフィルターを使い、ツリーの一番上ではプロジェクト設定rendering/textures/canvas_textures/default_texture_filterに従います。その既定値はLinearです。Linearは近くの4テクセルを混ぜるので、1倍より大きく描いた瞬間にすべてのピクセルの境目がなだらかな坂になります。
インポート。GodotはPNGをミップマップなしの可逆(Lossless)で取り込み、ドキュメントもドット絵に推奨する設定だとしています。ただしテクスチャを3Dマテリアルに使うとDetect 3Dがミップマップ付きのVRAM圧縮に切り替え、誰かが非可逆・VRAM圧縮を選んだり、Process › Size Limitが縮小したり(キュービック補間)すると変わります。カメラを引いて1倍未満で描くときも、ミップマップがスプライトをぼかします。
倍率。320 × 180のゲームを1920 × 1080のウィンドウに出すとちょうど6倍で、1ドットが画面の6 × 6ピクセルになります。1366 × 768では4.27倍なので、4ピクセル幅のドットと5ピクセル幅のドットが混ざり、線がでこぼこに見えます。これを決めるのがdisplay/window/stretch/mode、aspect、scale_modeで、scale_mode = integerにすると倍率を整数に切り捨てます。
動き。x = 10.4にあるスプライトやカメラは画面のピクセルの間に描かれます。Linearならぼけ、Nearestならちらつきになり、キャラクターと背景の丸め方が違うと片方が揺れて見えます。rendering/2d/snap/snap_2d_transforms_to_pixelはCanvasItemの位置を整数ピクセルに丸めます。
texture_filter- CanvasItemの属性:Inherit(親から継承)、Nearest、Linearとミップマップ付きの種類。ツリーの一番上ではプロジェクトの既定値が使われます。
display/window/stretch/modedisabled、canvas_items(2Dをウィンドウの解像度で描く)、viewport(ゲームを基準サイズで描画し、その画像をウィンドウに合わせて拡大)。display/window/stretch/scale_modefractionalは倍率をそのまま使い、integerは切り捨てて、画面を常に基準サイズの整数倍にします。rendering/2d/snap/snap_2d_transforms_to_pixel- CanvasItemの位置を整数ピクセルに丸めます。くっきりしますが動きのなめらかさは落ちます。起動時にだけ読まれます。
例:320 × 180のゲームを3つのウィンドウサイズで
基準サイズはdisplay/window/size/viewport_width × viewport_heightです。引き伸ばしの倍率はウィンドウサイズをこれで割った値です。
ウィンドウ 倍率 scale_mode = fractional scale_mode = integer
1920 × 1080 1920/320 = 6.00 1ドット = 6 × 6 px 6 × 6、画面いっぱい
2560 × 1440 2560/320 = 8.00 8 × 8 8 × 8
1366 × 768 768/180 = 4.27 ドット幅が4pxか5px 切り捨て → 4:1280 × 720 + 余白
4.27がだめな理由:32ドット × 4.27 = 画面136.5px — 均等に分ける方法がないaspect = keepなら余った部分は黒い帯になり、expandならその分だけレベルが広く見えます(Godotのドキュメントはドット絵にどちらかを勧めています)。整数倍率ではウィンドウが基準サイズより小さいと画面が切れるとドキュメントが注意しているので、Window.min_sizeを基準サイズにしてください。
Nerulioのバンドルが取り除く原因と、自分で直す原因
| 原因 | 設定の場所 | Godot 4バンドルで解決? |
|---|---|---|
| ノードのLinearフィルター | CanvasItem › Texture › Filter、またはプロジェクトの既定値 | バンドルのAnimatedSprite2Dだけ(texture_filter = 1、Nearest)。ほかのノードは引き続きプロジェクトの既定値を継承 |
| ミップマップ、非可逆・VRAM圧縮、Size Limit | PNGのインポート設定 | はい:同梱の.png.importはcompress/mode=0(可逆)、mipmaps/generate=false、process/size_limit=0 |
| アルファの縁で薄いピクセルの色が変わる | インポートオプション Process › Fix Alpha Border(既定でオン) | はい:process/fix_alpha_border=false |
| 小数の引き伸ばし倍率 | プロジェクト設定 › Display › Window › Stretch | いいえ — プロジェクト設定 |
| スプライト・カメラのサブピクセル位置 | rendering/2d/snap/*、スクリプト、Camera2Dのスムージング | いいえ — プロジェクト設定とコード |
| 整数でないCamera2Dのズーム(1.5) | Camera2Dノード | いいえ — 1、2、3…を使う |
| PNGの中ですでにぼけている絵 | 元の画像 | いいえ。バンドルは描いたとおりにまとめます。先にドット絵の1倍復元で1倍の絵を作り直してください |
できること
- .tscnがAnimatedSprite2Dにtexture_filter = Nearestを設定。プロジェクトの既定がリニアでもスプライトはくっきり。
- .png.importは可逆圧縮・ミップマップなし。
- fix_alpha_borderをオフに。Godotの既定はアルファ20未満のピクセルの色を変えます(実際の4096²エフェクトシートで測定)。バンドルの設定ではそのシートが合格しました。
- 検証ではGodotが同梱シーンを4倍で描画し、くっきりしたままでした。
使い方
- シート・フレーム・.asepriteを入れて読み込みを適用。
- パック&書き出しでGodot 4を選ぶ。
- バンドルのフォルダー(.png.import入り)をプロジェクトにコピー。
- ゲーム全体では Rendering › Textures › Canvas Textures › Default Texture Filter を Nearest にし、整数倍で拡大。
Godot 4でこの順に直す
- プロジェクト設定 › Rendering › Textures › Canvas Textures › Default Texture Filter = Nearest(ほかが高解像度のゲームなら、ドット絵のノードだけTexture › Filter = Nearest)。
- プロジェクト設定 › Display › Window › Sizeで、ビューポートの幅と高さをドット絵の解像度(例:320 × 180)にします。
- プロジェクト設定 › Display › Window › Stretch:Mode =
viewport、Aspect =keep(またはexpand)、Scale Mode =integer。Godotのドキュメントがドット絵に勧める組み合わせです。スプライトをサブピクセル位置で動かし回転させたいときだけcanvas_itemsを使います。 - 動くとちらつくなら
rendering/2d/snap/snap_2d_transforms_to_pixelをオンにしてプロジェクトを再起動します(起動時に読まれる)。ドキュメントはsnap_2d_vertices_to_pixelとの併用を勧めていません。 - ドット絵のPNGごとにインポートドックを確認:Compress › Modeが可逆、Mipmaps › Generateがオフ、薄いピクセルがあればFix Alpha Borderもオフ。変えたら再インポート。Nerulioのバンドル(AsepriteをGodotへ、スプライトシートをGodotへ)にはこの値がすでに入っています。
Camera2D.zoomとノードのスケールは整数に保ちます。
結果の確認
- 止まったスプライトを2Dエディターで800 %に拡大します。縁が四角ならNearest、なだらかならLinearです。
- 基準が320 × 180なら1920 × 1080のウィンドウで実行し、スクリーンショットを拡大します。1ドットがちょうど画面の6 × 6ピクセルのはずです。
- ウィンドウを1366 × 768にします。
scale_mode = integerなら余白が出て、ドットは4と5が混ざらない4 × 4でくっきりしたままです。 - カメラをゆっくり動かします。位置のスナップがオンなら、スプライトはちらつかず1ピクセルずつ動きます。
トラブルシューティング
| 症状 | 考えられる原因 | 確認方法 | 対処 |
|---|---|---|---|
| 止まっていても縁がぼける | Linearフィルター:ノードがプロジェクトの既定値を継承している | ノードを選び、Texture › Filterが継承で既定のフィルターがLinearか確認 | 既定のフィルターを一度Nearestに、またはそのノードのFilterをNearestに |
| 引いたときだけ、または3Dマテリアルに使ってからぼける | ミップマップかVRAM圧縮 — Detect 3Dがインポート設定を変えた | PNGのインポートドックで圧縮方式とミップマップ生成を確認。Detect 3Dが働くと出力パネルにメッセージが出る | 圧縮を可逆に、ミップマップをオフにして再インポート |
| 一部のドットだけ太く、斜めの線ががたがた | 小数の引き伸ばし倍率(4.27倍)や1.5のようなCamera2Dのズーム | ウィンドウサイズ ÷ 基準サイズ、Camera2Dのズーム値 | 引き伸ばしモードviewport+倍率モードinteger、ズームは整数に |
| 止まるとくっきり、動くとちらつく・揺れる | スプライトかカメラがピクセルの間にある(カメラ位置のスムージングでよく起きる) | 動いている間print(global_position)に10.4のような値が出る | snap_2d_transforms_to_pixelをオンにして再起動、またはコードで位置を丸める |
| 薄い光・煙のピクセルの色が変わる | 既定でオンのFix Alpha Borderが透明ピクセルを周りの色で埋める | インポートドックのProcess › Fix Alpha Border | オフにして再インポート — バンドルの.png.importはそう設定済み |
| 1920 × 1080ではくっきり、ノートPCやウィンドウサイズ変更でばらつく | 引き伸ばし倍率がウィンドウサイズで変わる | 1366 × 768で実行するか、ウィンドウを最大化してみる | 倍率モードinteger、Window.min_sizeを基準サイズに |
| 画像ビューアで800 %にしてもPNG自体がぼけている | Godotに来る前になめらかな補間でサイズ変更された絵 | Godotの外で元のファイルを開く | Godotの設定では直りません。先に1倍の絵を作り直してください |
ほかの方法
| 方法 | こんなときに向いています |
|---|---|
| 上の手順で一度だけプロジェクトをドット絵向けにし、PNGはそのまま取り込む | PNGに直接描いてSprite2Dを使うとき。既定の可逆インポートがすでに正しいので、フィルターと引き伸ばしだけ変えれば済みます。 |
| 一部のノードだけNearest | 高解像度のゲームにドット絵の要素が少しだけあるとき。プロジェクトの既定はLinearのまま、そのノードだけTexture › Filter = Nearest。 |
| NerulioのGodot 4バンドル | シートや.asepriteから始めて、アニメーション、Nearestのシーン、インポートファイルを一度に用意したいとき。 |
エンジン別の書き出しと検証方法
「検証済み」は、実際のCC0アセットから書き出したファイルを本物のエンジン・ツールで読み込み、元データと比較したという意味です。読み込んでいない形式はそのように表示します。
| 書き出し先 | ファイル | 検証 |
|---|---|---|
| Godot 4 | .tres SpriteFrames · .tscn AnimatedSprite2D · .png.import | 検証済み Godot 4.7.2Godotで読み込み、全アニメーションフレームを描画して元ファイルと比較。シーンはNearestフィルターで、回転は使いません。 |
| Unity 6 | .unity.json · Editor/NerulioSpriteImporter.cs · AnimationClip | 検証済み Unity 6000.5.3f1バッチモードでスプライト範囲・ピボット・ピクセル・クリップのキーと長さを確認。 |
| Phaser 3 / 4 | atlas JSON (multiatlas) · .anims.json | 検証済み Phaser 3.90 + 4.2両バージョンでフレームとアニメーションを描画。 |
| PixiJS 8 | spritesheet JSON · animations · anchor · meta.scale | 検証済み PixiJS 8.21回転・複数ページのアトラスも確認。 |
| Aseprite JSON | hash / array · frameTags · slices | 検証済み Phaser load.aseprite · PixiJS 8.21タグの方向と繰り返し回数を保持。 |
| .aseprite | layers · tags · durations · slices | 検証済み Aseprite 1.3.18Asepriteのコマンドラインで開いて描画。 |
| Spine / libGDX | .atlas | 検証済み spine-canvas 4.2Spineランタイムで回転・トリム領域をすべて描画。libGDX本体は未実行。 |
| Starling / Sparrow XML | XML per page | 検証済み Phaser 4.2Phaser 3.90はトリムされたXMLフレームを誤って描画します(Phaser側の不具合)。「Sparrow XML (Phaser 3)」プリセットはトリムを切り、3.90・4.2とも合格。 |
| LÖVE | Lua quads · nerulio_atlas.lua · main.lua | 検証済み LÖVE 11.5同梱ヘルパーで全フレームを描画し、全アニメーションを再生。 |
| Defold | .atlas · .tilesource | ビルド確認 Defold bob.jar 1.13.1Defoldのコマンドラインビルダーでビルドし、生成テクスチャのUVを読み戻して確認。 |
| GameMaker | spr_<name>_stripN.png · gamemaker.json | 未検証GameMakerでは読み込んでいません(ヘッドレス実行不可)。ストリップはGameMakerの取り込み方式どおりに切ります。 |
| CSS sprites | .css · preview .html | 検証済み Chromium同梱スタイルシートで全クラスを描画。 |
| GIF / APNG | one file per animation | デコード確認 Pillow書き出し後に全フレームと遅延を再デコード。APNGは完全一致。 |
検証の根拠
書き出し:実在のCC0アセットで実際のエンジンを49回実行し47回合格。失敗2回はPhaser 3.90のトリムXMLの不具合で、Phaser 3プリセットで回避。実在の5フレームセットでパッカー比較(CodeAndWeb無料Webパッカー、GAPTools、free-tex-packer):回転ありで5つすべて最小、回転なしで5つ中4つ。全フレームがピクセル単位で復元できます。
制限
- バンドルは
project.godotを書き換えません。既定のフィルター・引き伸ばし・スナップ・カメラは設定したままです。 - 書き出す前にぼけていたスプライトはぼけたままで、インポート設定でくっきり戻ることはありません。
- 上の引き伸ばし・スナップの設定はGodotのドキュメントに基づくもので、私たちのGodotでの実行はバンドルを検証したものです。
- ポリゴン(メッシュ)パッキングはありません。検証したエンジンのどれも、書き出しデータからメッシュアトラスを描画しないためです。
- GameMakerのストリップはGameMaker本体では未検証です。
- 拡大縮小バリエーション(@0.5x〜@4x)はニアレストネイバーのみです。
- トリムしたStarling XMLはPhaser 3.90で正しく描画されないため、「Sparrow XML (Phaser 3)」プリセットを使ってください。
バージョンと出典
検証の実行ではGodot 4.7.2がNerulioのバンドルを読み込み、同梱のシーンを4倍で描画してもくっきりしたままでした。Godot既定のFix Alpha Borderが薄いピクセルの色を変えていた4096²のエフェクトシートも、バンドルのインポートファイルでは合格しました。設定名・既定値・ドット絵向けの推奨はGodot 4.7のドキュメントに従っています(4.7で作ったプロジェクトは引き伸ばしモードcanvas_itemsで始まるという記述もあります)。
参照した公式ドキュメント
よくある質問
動かすとまだチラつくのはなぜ?
インポートではなくサブピクセル移動が原因です。2Dのピクセルスナップを有効にし、カメラとウィンドウの倍率を整数に保ってください。これらはバンドルが変えないプロジェクト設定です。
プロジェクトの何かが上書きされますか?
コピーしたバンドルフォルダー内のファイルだけです。プロジェクト設定はそのままです。
無料ですか?アカウントは必要ですか?
このページの機能はすべて無料で、アカウントなしで使えます。透かしや制限された書き出しはありません。
スプライトはアップロードされますか?
いいえ。Studioはこのブラウザのタブ内でデコード・パック・書き出しを行います。プロジェクトはブラウザ(IndexedDB)に自動保存され、.nerulioファイルとして保存できます。
Asepriteやエンジンのプラグインは必要ですか?
いいえ。.asepriteファイルはブラウザで読み書きします。エンジン別のバンドルには必要なものが入っています(Godotはインポート設定とシーン、UnityとGodotのタイルセットは小さなエディタースクリプト)。