フリップブックテクスチャ · 完全ガイド

フリップブックテクスチャ:Unity、Godot、VRChatでスプライトをアニメーションさせる方法

自分のフリップブックテクスチャを作る

フリップブックテクスチャは、スプライトシートを1つのサーフェス上でフレームごとに再生するものです。Unity、Godot、VRChatで作成する方法と、実際のスプライトシートを3D上でライブに動かす方法を学びましょう。

✦スプライト
フリップブックテクスチャを作成する素材:魔法のポータルループ

フリップブックテクスチャとは、シェーダーが1つのサーフェス上でフレームごとに再生するスプライトシートです。リグもタイムラインも存在せず、シートが固定グリッド内にすべてのフレームを保持し、マテリアルがそのグリッド上を一定の速度で小さなウィンドウを移動させます。8 x 8のシートには64フレームが含まれ、毎秒12フレームでは約5.3秒でループします。メッシュは変化せず、テクスチャの再アップロードもなく、アニメーション全体が1回のテクスチャルックアップで済みます。

このページでは、フリップブックシェーダーに必要な4つの数値とフレームインデックスがUV座標にどのようにマッピングされるか、Unityでフリップブックテクスチャを駆動する2つの方法、VRChatアバターでのPoiyomiフリップブックの設定方法、GodotとPhaserでの同等の手法、そしてGIFや文章による説明から独自のシートを構築する方法を解説します。

クイックアンサー

フリップブックテクスチャとは、シェーダーアニメーションとして使用されるスプライトシートで、時間の経過とともに行と列でインデックスされます。シートは1つのテクスチャスロットに配置され、シェーダーの評価ごとに経過時間とフレームレートからフレームインデックスを計算し、そのインデックスを列と行に変換して、サーフェスのUVをその単一セルに再マッピングします。frame = floor(time * fps) mod frameCount、column = frame mod columns、row = floor(frame / columns)。6 x 6のシートを10 FPSで再生すると、36フレームを3.6秒で循環し、すべてGPU上で処理され、フレームごとのアップロードもドローコールの変更もありません。

フリップブックテクスチャの仕組み

4つの数値がアニメーションを定義します。ColumnsとRowsはシートのレイアウトを表します。Frame countは通常Columns×Rowsで、インデックスが折り返す値です。Frame rateはインデックスが進む速度です。それ以外のすべて — フィルタリング、ラップモード、UVインセット — は、サンプラーが現在のセルの外側を読み取らないようにするために存在します。

インデックスの計算式は短く、書き出しておく価値があります。経過時間tが与えられた場合:frame = floor(t * fps) mod frameCount、column = frame mod columns、row = floor(frame / columns)。UVウィンドウは、tiling = (1 / columns, 1 / rows)、offset = (column / columns, row / rows)となります。多くの人がつまずくのは垂直方向です。ほとんどのシート作成ツールは画像の上部に行0を書き込みますが、UnityとGodotのUV原点は左下にあります。Unityで上段優先のシートを使用する場合、offset.yは1 - (row + 1) / rowsとなり、そうしないと行が反転して再生され、アニメーションの最初のフレームがシートの最終行になります。

フィルタリングが結果のクリーンさを決定します。シートのラップモードをClampに設定してください。Repeatでは、テクスチャの右端でのサンプルが左端を読み取るため、フレーム0のピクセル列が各行の最後のフレーム内に表示されます。ハードエッジのピクセルアートではミップマップをオフにしてください。ミップチェーンが隣接するセルを平均化し、サーフェスが数メートル離れるとアニメーションが崩れてしまいます。対象のエンジンやシェーダーがミップマップを強制する場合は、各セルの周囲に1~2ピクセルの透明なガターを残すか、UVウィンドウを4辺すべてでハーフテクセル分インセットしてください。

値制御する内容
Columns横に並ぶフレーム数。1セルの水平タイリング(1 / columns)を設定します。
Rowsシート内の行数。垂直タイリング(1 / rows)を設定します。ストリップの場合は1を使用します。
Frame countインデックスされるフレームの総数。通常はcolumns×rowsです。インデックスはここで折り返します。
FPSインデックスが進む速度。floor(time * fps)が現在のフレームを返します。
ラップモードClamp。Repeatではサンプラーがシートの端を越えて読み取ります。
フィルタモードPoint、ミップマップオフ、またはセルごとにUVをハーフテクセル分インセットします。

Unityでのフリップブックテクスチャ

2つの方法があり、それぞれ異なる形で失敗します。1つ目は、行と列のインデックスを自身で管理しアニメーションするシェーダーです。2つ目は、Animationウィンドウでマテリアルのタイリングとオフセットをキーフレームし、通常のLitまたはUnlitシェーダーがサンプリングを行う方法です。1つ目はゲーム時間と同期する必要があるエフェクトに適しており、2つ目はAnimatorステートによってアニメーションを駆動し、シーン内の他のすべてと一緒にタイムラインで表示する必要がある場合に適しています。

いずれの場合も、まずスプライトシートのインポート設定を行ってください:Wrap Mode Clamp、Mip Maps off、Filter Mode Point、ピクセルアートでは圧縮なし。これら3つの設定が、シェーダーの計算よりも多くのフリップブックのバグを引き起こします。

方法1:行と列のインデックスを持つシェーダー

Shader Graphでは、FlipbookノードがColumns、Rows、時間駆動のフレームインデックスを受け取り、再マッピングされたUVを出力します。手書きのシェーダーでは、_Columns、_Rows、_Fpsをプロパティとして公開し、頂点またはフラグメントステージでセルを計算します。オブジェクト間でアニメーションを同期させる必要がある場合は、各マテリアルで_Time.yを個別にサンプリングするのではなく、スクリプトのfloatからフレームインデックスを駆動してください。そうしないと、同じオブジェクト上の2つのフリップブックがずれる可能性があります。

方法2:Animationウィンドウでタイリングとオフセットを駆動する

この方法では、テクスチャの_STベクトルをアニメーション化します。ビルトインのStandardとUnlitは_MainTex_STを使用し、URP LitとUnlitは_BaseMap_STを使用します。Tilingは(1, 1 / rows)に固定され、offset.yのみが変化します。以下の手順はこの方法に適用されます。

1

01

マテリアルを選択し、Animationウィンドウを開きます。クリップを作成し、テクスチャの_STベクトルプロパティをトラックとして追加します — マテリアル上でVector4として表示されます。

2

02

クリップのサンプルレートを、目標とするFPSと同じ数値に設定します。サンプルレートが目標のFPSより低い場合、キーフレームが同じサンプルに集約され、アニメーションが意図したよりも遅く再生されます。

3

03

offset.yを1フレームに1回キーフレームします:上段優先のシートの場合、value = 1 - (row + 1) / rows、tiling = (1, 1 / rows)。

4

04

カーブエディタで、すべてのキーフレームの補間をConstantに設定します。Linearでは2つのセルがブレンドされ、両方のフレームが同時にゴーストとして表示されます。

5

05

最後のキーが最初のフレームの値を繰り返さないようにしてください。そうしないと、ループの継ぎ目でアニメーションが1フレーム停止します。

6

06

複数のレンダラーがマテリアルを共有している場合は、renderer.materialを読み取るのではなく、レンダラーごとにMaterialPropertyBlockをアニメーション化してください。renderer.materialは最初にアクセスしたときにマテリアルを複製し、そのクローンがオブジェクトの寿命まで残ります。

VRChat向けPoiyomiフリップブック

PoiyomiシェーダーのFlipbookセクションは、マテリアル自体でUVウィンドウをシート上でスクロールさせるため、1つのマテリアルスロットでアバターメッシュ上のアニメーションスプライトを表示できます。Rows、Columns、フレームレートが公開されており、シェーダー時間で実行させる代わりにフレームインデックスを自分で駆動するモードもあります。

グリッドではなく単一行のストリップを使用してください。ストリップではシェーダーがステップする軸が1つになるため、垂直方向の継ぎ目が完全に排除されます。グリッドの場合、UVウィンドウは各行の終わりに次の行へ移動する必要があり、その境界でのフィルタリング、ミップレベル、ハーフテクセルの丸め誤差によって隣接する行がサンプリングされます — 再生中に異なるフレームの細い帯として見えます。ストリップではフレームインデックスも単純な乗算になります:UVでのフレーム幅は1 / frameCount、オフセットはframe / frameCountです。256 x 256セルの8フレームアニメーションの場合、ストリップは2048 x 256となり、2のべき乗を維持します。

アルファはフラットなシーンよりもアバターでより重要です。スプライトにハードエッジがある場合は、CutoutまたはOpaqueを使用してください。Transparentキューのフリップブックは深度を書き込まず、アバター上ではボディや互いにソートされ、カメラアングルによって挙動が変化します。可能であれば、アニメーションするサーフェスをすでにアバターにあるマテリアルに配置してください — 追加のマテリアルスロットはアバターのパフォーマンスランクに影響します。同期パラメータを持つAnimatorステートからフレームインデックスを駆動すると、すべてのクライアントが同じフレームを表示します。シェーダー時間から計算されたフレームインデックスはローカルで評価され、視聴者によってループの異なる位置になる可能性があります。

1

01

フレームを1つの水平ストリップとしてエクスポートします。ストリップの高さはセルの高さ、幅はフレーム数×セル幅です。末尾に予備のセルを残さないでください。

2

02

テクスチャをWrap Mode Clamp、Mip Maps off、sRGB onでインポートします。Alpha Is Transparencyは、ストリップが実際にアルファを持つ場合のみ有効にしてください。

3

03

Poiyomiマテリアルを作成し、アニメーションするメッシュに割り当て、Flipbookセクションを開きます。

4

04

Rowsを1に、Columnsをフレーム数に設定します。フレームレートを希望する持続時間に合わせます — 8フレームを8 FPSで再生すると1秒のループになります。

5

05

フレームソースを選択します。ManualモードではAnimatorステートから駆動するフレームインデックスが公開され、時間駆動モードでは自動的にループします。

6

06

Renderingで、ハードエッジのスプライトにはCutoutまたはOpaqueを設定します。Transparentはソフトエッジのエフェクトにのみ残し、深度ソートの問題を想定してください。

7

07

ループを確認します:最後のフレームが最初のフレームの複製であってはなりません。そうしないと、サイクルごとにスプライトが1フレーム停止します。

8

08

アップロードしたアバターでミラーを使い、近距離とインスタンスの反対側からテストします。距離がミップとフィルタリングの問題が現れる場所です。

GodotとPhaserでのフリップブック

Godot 4では、2Dの方法はSpriteFramesリソースを持つAnimatedSprite2Dです。シートをインポートし、SpriteFramesを開き、HframesとVframesを列数と行数に設定し、アニメーションのフレームを追加してから、アニメーションの速度をフレーム毎秒で設定し、Loopをオンにします。SpriteFramesはアニメーションをフレームインデックスのリストとして保存するため、グリッドシートも単一ストリップもUV計算なしで機能します。

アニメーションが1つだけ必要な場合は、通常のSprite2Dの方が軽量です:HframesとVframesを一度設定し、AnimationPlayerから整数のframeプロパティをステップ補間で進めます。デフォルトのイージングカーブでframeをトゥイーンしないでください — 値は整数インデックスであり、補間すると単一の値に切り捨てられるか、2つのセル間でちらつきます。

Godotで3Dサーフェス上のフリップブックの場合、Unity版と同じ行と列の計算を持つShaderMaterialが最短経路です:uv = UV * vec2(1.0 / cols, 1.0 / rows) + vec2(col / cols, row / rows)、行はフレームインデックスから計算します。GodotのUV原点はUnityと同じ左下なので、上段優先のシートには同じ垂直反転が必要です。

Phaser 3では、シートは一度ロードされ、ロード時にスライスされます。frameWidthとframeHeightがセルを定義し、framesは左から右、上から下に番号が付けられ、アニメーションは座標ではなくフレーム番号で識別されます — シェーダーを書く必要も、間違える可能性のある行と列の計算もありません。

エンジンオブジェクト設定する内容
Godot 4AnimatedSprite2D + SpriteFramesHframesとVframesをシートレイアウトに設定し、アニメーション速度をFPSで設定してLoopを有効にします。
Godot 4Sprite2DHframesとVframesを一度設定し、整数のframeプロパティをAnimationPlayerでステップ補間して進めます。
Godot 43Dメッシュ上のShaderMaterialシェーダー内のcolumns、rows、フレームインデックス。Unityと同じUV再マッピングと垂直反転を使用します。
Phaser 3this.load.spritesheetframeWidthとframeHeight。Phaserはシートを左から右、上から下にスライスします。
Phaser 3this.anims.createanims.generateFrameNumbersからのフレーム、frameRate、およびループするにはrepeat: -1。

3D上でスプライトシートをライブに動かす

このセクションのプレイアブルシーンは、Neta Studioの3Dゲームビルダーで動作するThe Cyclops' Islandです。画面上のフリップブックは、上述したものと同じインデックスからUVへの操作であり、Three.jsシェーダーでGPU上で評価されています — 違いは、実際のメッシュ、実際のシーン上で動作し、操作できるカメラと動くライトがあることです。

これは聞こえ以上に重要です。フラットなUnityシーンでのフリップブックは通常正面から見られるため、継ぎ目のにじみやミップブレンドは見えにくいものです。アニメーションするサーフェスの周りを浅い角度でカメラを動かすと、問題がすぐに現れます:フレームエッジでの隣接セルの帯、最後のミップレベルが2つのフレームを平均化してぼやける、または正面からは正しく見えるアルファエッジが横から消えるなどです。ブラウザビルドは、シートの作成とサーフェス上での確認の間のループを、ビルドステップなしで反復できるほど短くします。

Mini Worldは、単一のシートをテストするためにより小さなシーンです — メッシュ数が少なく、ロードが短くなっています。Agent Sprite Forgeは、まだシートがない場合にフレームを生成し、両方のシーンが同じフリップブックパスで動作するため、Mini Worldで正しく見えるシートはThe Cyclops' Islandでも同じように動作します。

メイジキャスト — 4フレームのストリップ(フレームあたり577×686)、まさにフリップブックシェーダーが求める入力です。

自分のシートを作る

使用可能なシートへのルートは3つあります:既存のGIFを変換する、グリッドを単一のストリップに切り出す、または文章による説明からフレームを生成する。3つとも同じファイルに到達します — すべてのセルが同じサイズで、左から右、上から下に配置され、シートの幅がセル幅のきれいな倍数である1つのPNGです。

GIFの変換は、最も隠れた作業が多いルートです。GIFは完全なフレームの連続ではないからです。フレームはしばしば前のフレームに対する部分的な差分であり、遅延は100分の1秒単位でフレームごとに保存されます。フリップブックシェーダーは1つのフレームレートしか受け付けないため、可変タイミングはエクスポート前に重複フレームに平坦化する必要があります。

グリッドをストリップに切り出すのは機械的です:必要な行を保持し、高さを1セルにクロップし、幅をフレーム数×セル幅のままにします。グリッドシートを単一のアニメーションとして使用する場合に適した方法です。垂直軸とそれに伴う継ぎ目が排除されるからです。説明から生成するのが3つ目のルートです — Agent Sprite Forgeはアクションとフレーム数を受け取り、固定セルサイズのシートを返します。これにより、1つずつエクスポートしたフレームを手作業で位置合わせする必要がなくなります。

1

01

エクスポート前にすべてのGIFフレームを平坦化します。各フレームを前のフレームを引き継ぐキャンバスにデコードしてください。そうしないと、画像ではなく差分矩形をエクスポートすることになります。

2

02

タイミングを正規化します。GIFの最短または中央値の遅延を選び、ソースがより長く保持していたフレームを複製して、シートが1つの一定なFPSで再生されるようにします。

3

03

フレームを左から右、上から下に配置し、すべてのセルを同一サイズにします。シートの寸法をセルサイズの正確な倍数にしてください — 幅が9.5セルのシートは永遠に間違ったテクセルをサンプリングします。

4

04

ストリップに切り出すには、高さを1セルにクロップし、幅をフレーム数×セル幅のままにします。ソースグリッドに空の末尾セルがあった場合は削除します。

5

05

対象のエンジンでミップマップを無効にできない場合は、各セルの周囲に1~2ピクセルの透明なガターを追加します。それ以外の場合は、UVウィンドウを4辺すべてでハーフテクセル分インセットします。

6

06

変換ではなく生成するには、アクション、フレーム数、向きを記述し、Agent Sprite Forgeに固定セルのシートを返させます。1つずつエクスポートして手作業で位置合わせする代わりになります。

7

07

エンジンでフレームインデックスを1つずつステップして確認します。いずれかのセルが端で隣接セルの断片を示す場合、問題はシェーダーではなく、シートレイアウトまたはUVインセットにあります。

The Cyclops' Island — ライブ3Dシーンのサーフェス上で動作するフリップブックアニメーション。

その世界に足を踏み入れる

スプライトは立ち場所のないキャラクターです。最後のステップは、他にはないものです:今作成したシートを、誰かが歩き回れる世界に配置します — 小さな島、惑星、雨の降る街角。このサイトのすべての世界は1つの文章による説明から作られ、プレイできるページとして公開されています。

FAQ

Poiyomiフリップブックとは何ですか? +

PoiyomiシェーダーのFlipbookセクションで、マテリアル上のスプライトシートをUVウィンドウがスクロールし、1つのマテリアルスロットでアバターメッシュ上のアニメーションスプライトを表示できるようにするものです。Rows、Columns、フレームレートを設定し、フレームインデックスをシェーダー時間で実行させるか、Animatorステートから駆動します。単一行のストリップが推奨されます。行間の垂直方向の継ぎ目が排除されるからです。

GIFを直接フリップブックにできますか? +

いいえ。GIFはフレームごとの遅延を保存し、多くの場合変更されたピクセルのみを保存しますが、フリップブックシェーダーは1つのテクスチャと1つの一定のフレームレートを期待します。まず変換してください:すべてのフレームを前のフレームに合成し、タイミングを正規化し、結果を固定セルグリッドに書き込みます。シェーダーはGIFを認識しません。

フリップブックテクスチャがフレーム間でにじむのはなぜですか? +

サンプラーが現在のセルウィンドウの外側を読み取っています。テクスチャのラップモードをClampに設定し、ハードエッジのアートではミップマップをオフにし、UVウィンドウを両側でハーフテクセル分インセットしてください。にじみは距離が離れるほど悪化します。ミップチェーンが隣接するセルを平均化し始めるからです。

フリップブックにはどのフレームレートを使うべきですか? +

8~12 FPSは手描きアニメーションとして認識され、キャラクタースプライトに適しています。24~30は火、水、その他の連続エフェクトに適しています。シェーダーには正確に1つのレートしかないため、ソースに可変タイミングがあった場合は、ループの途中で速度を変えようとするのではなく、フレームを複製して合わせてください。

グリッドが必要ですか、それとも1行で十分ですか? +

シーケンスとして再生されるものには1行で十分で、継ぎ目エラーの軸が1つ減ります。グリッドは、複数のアニメーションを1つのテクスチャに詰め込むシート用で、シェーダーやエンジンが待機、走り、攻撃のために行を選択します。グリッドシートから1つのアニメーションしか出力しない場合は、ストリップに切り詰めてください。

フリップブックはUnity URPのLitシェーダーで動作しますか? +

そのままでは動作しません — URP Litにはフレームインデックスがありません。Columns、Rows、時間駆動のインデックスを受け取るFlipbookノードを持つShader Graphを使用するか、Constantキーフレーム補間でマテリアルの_BaseMap_STのタイリングとオフセットをアニメーション化してください。ビルトインのStandardとUnlitは同じルールで_MainTex_STを使用します。

3Dゲームビルダーに戻る

完成した31の3D世界、ゲーム、シーンはすべて1つのページにあり、すべてプレイ可能です。

プラットフォーム: Neta Studioページ: フリップブックテクスチャ:Unity、Godot、VRChatでスプライトをアニメーションさせる方法次に読む: /explore/tool/gif-to-flipbook · /explore/tool/gif-to-sprite-sheet · /explore/guide/sprite-sheet

スプライトアセットライブラリを開く

このライブラリのすべてのアセットは、記録されたプロンプト付きの透過ゲーム対応PNGです — スプライトシートリソースと無料スプライトシート、アクション、スタイル、被写体でタグ付けされています。閲覧とダウンロードは無料です。

×