スプライトアニメーションパイプライン は何をしますか?
連番フレームまたはスプライトシートをGodot 4、Unity 6、Phaser 3にインポートします。アニメーションのタイミング、アトラス参照、ピボットを修正します。
プロジェクトの規約、インストール済みバージョン、アーキテクチャ、アートスタイル、およびユーザーの明示的な選択が優先されます。
タイミングのみを変更するタスクの場合は、動作しているシートとフォーマットを維持します。スライスと再パッキングはオプションです。
このワークフローは既存のアートを使用し、新しいアニメーションを生成しません。新しいフレームは pixo media generate --sheet <C>x<R> --frames(プロンプトのメディアセクション)から生成され、すでに1つのキャンバス上に書き出されます。
クイックパス
- 選択したシートまたはフレームを
pixo asset info <path> --jsonで検査し、現在のクリップ定義を読み取ります。 - セルサイズと順序、クリップ範囲、ベースライン、ピボット、ループまたはワンショットのタイミングを確認します。
pixo asset frames check <frames...> --jsonはベースラインとドリフトを自動で測定します。 - 直接シートまたはパックのブランチを選択し、操作の実際の出力パスを読み取ります。
- ゲームプレイのコリジョンを移動せずに、エンジンの既存のアニメーションオーナーを介して統合します。
pixo game verify --steps check,build,run --screenshot --jsonを実行し、ログとフレームを検査した後、完全なループとワンショットをインタラクティブに確認します。
コマンドは PIXO_PROJECT_ID を前提としています。それ以外の場合は --project <id> を追加します。
以下のパスとフレーム数は例です。メタデータのないシートは独自のクリップを識別しません。
Unityには run ステップとスクリーンショットはありません。--steps check,build を使用し、エディターでクリップを確認します。
最小限のフォーマット変更を選択
| 入力またはリクエスト | 選択 | 維持するもの |
|---|---|---|
| 動作中の通常シート、タイミングのみの変更 | 既存のSpriteFrames、Unityクリップ、またはPhaserシート | フレーム範囲、テクスチャキー、共有ベースライン |
| 通常グリッドを個別フレームに分割する必要がある | pixo asset slice --cell WxH または --grid CxR と入力パス | マージン、スペーシング、期待されるカバレッジ |
| フレームがぐらつく、ずれる、またはサイズが異なる | pixo asset frames check、続けて frames align | 入力順序、すべてのフレームに1つのスケール |
| Godot用の連番PNG | pack --format godot-tres | 入力順序。PNGとTRESは一緒に保持 |
| Phaser用の連番PNG | pack --format texturepacker-json | 入力順序、実際のディスクリプタキー |
| Unity用のシートまたはフレーム | Unityでスプライトとしてインポートしてスライス。pack にUnity出力はなし | ピボット、Pixels Per Unit、既存の .meta |
| カスタムピボットでトリミングされたフレーム | 既存のメタデータ対応パイプライン | トリミングオフセットとピボット。画像のみのパッキングでは復元不可 |
関連するコントラクトフィールドのみを記録します:キャンバスとセルサイズ、行優先順序、クリップ範囲、FPS、フレームホールド、ループ、および足のベースライン。 等しいサイズのキャンバスと共有アンカーはフレーム間のぐらつきを防ぎます。不透明境界はピボットではありません。
スライスとパッキングアンカー
pixo asset slice public/assets/player.png --cell 32x32 --out derived/player-frames --dry-run --json
pixo asset slice public/assets/player.png --cell 32x32 --out derived/player-frames --json
pixo asset pack sprites/run/frame-0000.png sprites/run/frame-0001.png --format godot-tres --padding 1 --out derived/run-godot --json
pixo asset pack public/sprites/run/frame-0000.png public/sprites/run/frame-0001.png --format texturepacker-json --padding 1 --out public/atlases/run --json
スライスレポートの返されたPNGパスを使用します。2フレームのパックコマンドは順序の説明のみです。
--grid はマージンとスペーシング後の正確な分割が必要です。--cell は不完全なエッジセルを使用しない場合があります。
完全なカバレッジとフレーム数を確認します。他のクリップからの空セルとフレームは意図的に除外します。
results、extraOutputs、reportPath、失敗、originalsPreserved を読み取ります。既存の出力先はスキップされます。
パッカーの事実:
- ステムは最初の入力から派生し、
--out以下の相対ディレクトリを保持します。推測ではなくパスを読み取ります。 - 出力は
<stem>.atlas.pngと.atlas.tresまたは.atlas.jsonです。 - パッキングは空間配置を再配置する場合がありますが、ディスクリプタは入力順序を保持します。
- 回転、トリミング、エッジ押し出し、クリップ名付け、カスタムピボットは生成されません。
- パディングは透明な分離であり、複製されたエッジピクセルではありません。
フレームのチェックと整列
pixo asset frames check public/assets/hero/hero-run-1.png public/assets/hero/hero-run-2.png public/assets/hero/hero-run-3.png --json
pixo asset frames align public/assets/hero/hero-run-*.png --canvas 64x64 --padding 1 --out derived/hero-run --json
フレームを再生順に渡します(シェルグロブは -10 を -2 より前にソートします。10枚以上の場合はリストで指定)。
frames check は画像を書き出しません。フレームごとに、results[].detail は描画された bounds、bottomGap(足の下の行数)、feetX(最下行の中心、振られた武器は移動しない)、empty、touchesEdge を持ちます。
summary はセットを評価します:baselineSpreadPx(足の上下動)、feetXSpreadPx(横滑り)、heightDriftPercent、emptyFrames、edgeFrames、および issues 内の問題ごとの平文の文。問題がない場合 ok はtrueです。
しゃがみ、潰れ、ジャンプは意図的に高さを変えます。異なる高さの同じポーズはモデルのドリフトです。
frames align は各フレームを1つのキャンバス上の <out>/<入力パス>.png に書き出します。足は padding だけ底から上の1行、feetX は中心線、すべてに1つのスケールで、しゃがみは立ち姿勢より短くなります。
--canvas WxH はすべてのフレームを同じ係数でスケールして収めます。指定しない場合、キャンバスはすべてを収める最小サイズになります。
--match-height は最初に各描画を中央値の高さにスケールします(ドリフトのみ)。--filter nearest はピクセルアートを鮮明に保ちます。
その summary は整列されたフレームを再チェックします。既存の出力は、他のすべてのアセット操作と同様にスキップされます。
Godot 4: SpriteFramesタイミング
godot-tres は形式3のSpriteFramesを出力し、ループする default クリップを5 FPSで含みます。
PNGとTRESは一緒に保持します。テクスチャ参照は相対パスです。pixo game verify --steps check --json で新しい画像をインポートします。
報告されたパスを置き換えた後、これは実際の4フレームクリップを適応する例です:
func configure_run(sprite: AnimatedSprite2D) -> void:
var packed := load("res://sprites/run/run.atlas.tres") as SpriteFrames
if packed == null or packed.get_frame_count(&"default") != 4:
push_error("Expected four run frames")
return
var frames := packed.duplicate() as SpriteFrames
frames.rename_animation(&"default", &"run")
frames.set_animation_speed(&"run", 10.0)
frames.set_animation_loop(&"run", true)
frames.set_frame(&"run", 0, frames.get_frame_texture(&"run", 0), 2.0)
sprite.sprite_frames = frames
sprite.centered = true
sprite.offset = Vector2(0, -16) # 例: 32pxキャンバス上の下端中央アンカー
sprite.play(&"run")
フレーム持続時間 2.0 は通常のフレーム持続時間の2倍を意味し、2秒ではありません。
合意されたベースラインをオフセットに使用します。CharacterBody2DとCollisionShape2Dは安定させます。
ワンショットクリップは loop=false が必要です。animation_finished を一度接続し、アクティブなアニメーションで遷移をゲートします。
参照: Godot 4.3 SpriteFrames
Phaser 3: シートまたはアトラスのタイミング
// preload()、実際の32pxシートの場合:
this.load.spritesheet('player', 'assets/player.png', { frameWidth: 32, frameHeight: 32 });
// create()、プロジェクトの実際のラン範囲を使用:
if (!this.anims.exists('player-run')) {
this.anims.create({ key: 'player-run',
frames: this.anims.generateFrameNumbers('player', { start: 2, end: 5 }),
frameRate: 10, repeat: -1 });
}
player.setOrigin(0.5, 1).play('player-run', true);
ViteのパブリックアセットはURLに public/ を含めずに読み込まれます。
アトラスの場合、this.load.atlas(key, pngUrl, jsonUrl) で返されたペアを読み込みます。
TexturePackerのハッシュキーは入力のプロジェクト相対パスです。それらを読み取るか、getFrameNames() を使用します。
名前が順序をエンコードしない場合は、明示的な順序付きリストを使用します。
// orderedNames はレビュー済みのディスクリプタ/クリップリストから取得。
this.anims.create({ key: 'hero-run', frameRate: 10, repeat: -1,
frames: orderedNames.map((frame, index) => ({
key: 'hero-atlas', frame, duration: index === 0 ? 100 : 0,
})),
}); // 10 FPSでは、100msの追加で最初のフレームが合計200ms保持される。
グローバルアニメーション生成は上記のように this.anims.exists でガードします。キーはScene再起動後も生存します。
repeat: 0 は1回再生。所有するワンショット完了リスナーを使用します。
originの変更はボディ配置に影響します。悪いピボットを隠すためにコリジョンを移動するのではなく、サイズとオフセットを検査します。
参照: Phaser 3.90 アニメーションタイプ
Unity 6: インポーター、クリップ、Animator
Unityは追加パッケージなしでは godot-tres もTexturePacker JSONも読み取りません。シートを Assets/ に置き、Texture Type Sprite、Sprite Mode Multiple、実際のPixels Per Unitを設定します。ピクセルアートの場合は、Pointフィルターと圧縮なしを追加します。Sprite Editorでセルサイズでスライスし、Bottomなどの共有ピボットを使用します。スクリプトによるスライスは SpriteDataProviderFactories の ISpriteEditorDataProvider を介します。TextureImporter.spritesheet は古いパスです。com.unity.2d.aseprite は .aseprite ファイルを直接インポートし、アートがそこから始まる場合にクリップも含みます。
クリップはスプライトを選択してAnimationウィンドウにドロップするか、多数ある場合はスクリプトから作成できます。このエディターのみの例は、4フレームのループクリップを作成し、最初のフレームをホールドします:
using System;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
public static class HeroClips
{
[MenuItem("Tools/Create Hero Run Clip")]
public static void CreateRun()
{
const float frame = 0.1f; // 10 FPS
// LoadAllAssetsAtPathは順序を保証せず、hero_10はテキストとしてhero_2より前にソートされる
var sprites = AssetDatabase.LoadAllAssetsAtPath("Assets/Art/hero.png").OfType<Sprite>()
.OrderBy(sprite => int.Parse(Regex.Match(sprite.name, @"\d+$").Value))
.Skip(2).Take(4).ToArray();
if (sprites.Length != 4) throw new InvalidOperationException("Expected four run frames");
var keys = sprites.Select((sprite, index) => new ObjectReferenceKeyframe {
time = index == 0 ? 0f : (index + 1) * frame, value = sprite,
}).ToArray();
var clip = new AnimationClip { frameRate = 1f / frame };
AnimationUtility.SetObjectReferenceCurve(clip,
EditorCurveBinding.PPtrCurve("", typeof(SpriteRenderer), "m_Sprite"), keys);
var settings = AnimationUtility.GetAnimationClipSettings(clip);
settings.loopTime = true;
settings.stopTime = (sprites.Length + 1) * frame;
AnimationUtility.SetAnimationClipSettings(clip, settings);
AssetDatabase.CreateAsset(clip, "Assets/Animations/hero_run.anim");
}
}
キータイムは秒単位であるため、ホールドはキー間の広いギャップです。最後のフレームが完全な長さを得られるように stopTime を設定します。
- Animatorでは、スプライト遷移は通常Has Exit Timeをオフ、Transition Durationを0にするか、次のポーズが遅れて到着します。
animator.Play(hash)はすでに再生中の状態をそのままにするため、毎フレーム呼び出しても安全です。ワンショットの再再生にはPlay(hash, 0, 0f)が必要です。ハッシュ名はAnimator.StringToHashで一度だけ行います。- ワンショットの終了を検出するには、Animation Eventを使用するか、
IsInTransition(0)がfalseでステートハッシュが一致するときにnormalizedTime >= 1をチェックします。遷移中はそうでなければ古い状態を報告する可能性があります。 - AnimatorとSpriteRendererは子オブジェクトに配置し、Rigidbody2Dとコライダーはルートに配置し、Apply Root Motionをオフにします。
flipXはコライダーや子オブジェクトを反転せず、ピボットを中心にミラーリングするため、中央から外れたピボットはジャンプします。 - タイトなスプライトメッシュはフレーム上に描画されるエフェクトをクリップする可能性があります。シェーダーがアウトラインを超えてサンプリングする場合はFull Rectを使用します。
- Sprite Atlasは別々にインポートされたフレームをバッチングします。パディングを指定し、ピクセルアートの場合はTight PackingとAllow Rotationをオフにします。
落とし穴: 誤 → 正
| 誤 | 正、および理由 |
|---|---|
| パディングなしのファイル名を辞書順でソート | 明示的な順序。frame-10はframe-2より前に来るため |
| 各フレームを独立してトリミング | キャンバスまたは有効なオフセットを維持し、足を固定 |
| パックされたベース名を推測 | ディスクリプタキーと返された出力パスを読み取る |
| すべてのエンジンで同じ持続時間単位を使用 | Godotは相対乗数、Phaserフレーム持続時間はミリ秒追加、Unityキーは秒 |
毎フレーム play(key) を呼ぶ | play(key, true) ですでにアクティブなクリップの再起動を防ぐ |
| 視覚的なクリップ速度が暗黙的にダメージや物理を変更するのを許す | 明示的に結合されていない限り、ゲームプレイタイミングを権威あるものにする |
完了条件
- 実際のフレーム数、フレーム順序、クリップタイミング、ループ、ワンショット動作がリクエストと一致する。
- アイドルとランの間の遷移、ミラーリング、再起動を通じて、足とピボットが安定している。
pixo asset frames checkが各状態でokを報告するか、残りの問題は意図的なものである。 - アトラス参照とロードパスが実際のものである。視覚的な変更はコリジョン動作を維持する。
-
pixo game run <projectId> --json、またはUnityではエディターを使用して、完全なループとワンショットの完了を確認する。静止画像ではタイミングを証明できない。テストしたタイミングと未解決の問題を報告する。 -
pixo game verify --steps check,build,run --screenshot --jsonを検査し、リソースエラーとスキップされたステップを含む。