本文へスキップ

Godotでドット絵がぼやける? くっきり保つインポート設定

Godotでドット絵がぼやける原因は、たいていリニアフィルター、非可逆・ミップマップ付きのインポート、整数でない拡大です。StudioのGodotバンドルはファイルに入る部分を直し、残りのプロジェクト設定は下にまとめました。

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

パックするフレーム画像、GIF、.asepriteファイルをドロップ
空のStudioを開く
ブラウザ内で処理し、ファイルはアップロードされません。
Studio のパック&書き出し:各フレームの枠が表示されたアトラスページ、使用率、書き出し先
CC0アセット(OpenGameArt)を開いた実際のStudio画面です。
書き出し先
  • 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/mode
disabled、canvas_items(2Dをウィンドウの解像度で描く)、viewport(ゲームを基準サイズで描画し、その画像をウィンドウに合わせて拡大)。
display/window/stretch/scale_mode
fractionalは倍率をそのまま使い、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 LimitPNGのインポート設定はい:同梱の.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倍で描画し、くっきりしたままでした。

使い方

  1. シート・フレーム・.asepriteを入れて読み込みを適用。
  2. パック&書き出しでGodot 4を選ぶ。
  3. バンドルのフォルダー(.png.import入り)をプロジェクトにコピー。
  4. ゲーム全体では Rendering › Textures › Canvas Textures › Default Texture Filter を Nearest にし、整数倍で拡大。

Godot 4でこの順に直す

  1. プロジェクト設定 › Rendering › Textures › Canvas Textures › Default Texture Filter = Nearest(ほかが高解像度のゲームなら、ドット絵のノードだけTexture › Filter = Nearest)。
  2. プロジェクト設定 › Display › Window › Sizeで、ビューポートの幅と高さをドット絵の解像度(例:320 × 180)にします。
  3. プロジェクト設定 › Display › Window › Stretch:Mode = viewport、Aspect = keep(またはexpand)、Scale Mode = integer。Godotのドキュメントがドット絵に勧める組み合わせです。スプライトをサブピクセル位置で動かし回転させたいときだけcanvas_itemsを使います。
  4. 動くとちらつくならrendering/2d/snap/snap_2d_transforms_to_pixelをオンにしてプロジェクトを再起動します(起動時に読まれる)。ドキュメントはsnap_2d_vertices_to_pixelとの併用を勧めていません。
  5. ドット絵のPNGごとにインポートドックを確認:Compress › Modeが可逆、Mipmaps › Generateがオフ、薄いピクセルがあればFix Alpha Borderもオフ。変えたら再インポート。Nerulioのバンドル(AsepriteをGodotへ、スプライトシートをGodotへ)にはこの値がすでに入っています。
  6. 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 / 4atlas JSON (multiatlas) · .anims.json検証済み Phaser 3.90 + 4.2両バージョンでフレームとアニメーションを描画。
PixiJS 8spritesheet JSON · animations · anchor · meta.scale検証済み PixiJS 8.21回転・複数ページのアトラスも確認。
Aseprite JSONhash / array · frameTags · slices検証済み Phaser load.aseprite · PixiJS 8.21タグの方向と繰り返し回数を保持。
.asepritelayers · tags · durations · slices検証済み Aseprite 1.3.18Asepriteのコマンドラインで開いて描画。
Spine / libGDX.atlas検証済み spine-canvas 4.2Spineランタイムで回転・トリム領域をすべて描画。libGDX本体は未実行。
Starling / Sparrow XMLXML per page検証済み Phaser 4.2Phaser 3.90はトリムされたXMLフレームを誤って描画します(Phaser側の不具合)。「Sparrow XML (Phaser 3)」プリセットはトリムを切り、3.90・4.2とも合格。
LÖVELua quads · nerulio_atlas.lua · main.lua検証済み LÖVE 11.5同梱ヘルパーで全フレームを描画し、全アニメーションを再生。
Defold.atlas · .tilesourceビルド確認 Defold bob.jar 1.13.1Defoldのコマンドラインビルダーでビルドし、生成テクスチャのUVを読み戻して確認。
GameMakerspr_<name>_stripN.png · gamemaker.json未検証GameMakerでは読み込んでいません(ヘッドレス実行不可)。ストリップはGameMakerの取り込み方式どおりに切ります。
CSS sprites.css · preview .html検証済み Chromium同梱スタイルシートで全クラスを描画。
GIF / APNGone 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のタイルセットは小さなエディタースクリプト)。