Communitygithub.com

スプライトアニメーションパイプライン

既存のスプライトシートやフレームをGodot 4、Unity 6、Phaser 3にインポートし、スライス、アトラス参照、ピボット、タイミングを修正します。アート生成やスケルトンリグは対象外です。

スプライトアニメーションパイプライン とは?

このスキルは、既存のスプライトシートまたは連番フレーム画像を、Godot 4、Unity 6、Phaser 3の各ゲームエンジンにインポートするためのパイプラインを提供します。主な機能は、アニメーションのタイミング修正、アトラス参照の更新、ピボット位置の調整、フレームのスライスと再パッキングです。プロジェクトの規約やアーキテクチャ、アートスタイルを優先し、ユーザーの明示的な選択を尊重します。`pixo asset` コマンド群を使用して、フレーム情報の確認、グリッドスライス、フレーム位置のチェックと整列、エンジン固有のフォーマットへのパッキングを行います。また、`pixo game verify` によるビルド・実行の検証もサポートしており、アニメーションのループやワンショットの動作を確認できます。新しいアートの生成は行わず、既存のアセットを再利用することに特化しています。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/OpenPixo/OpenPixo/tree/HEAD/skills/sprite-animation-pipeline

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

スプライトアニメーションパイプライン は何をしますか?

連番フレームまたはスプライトシートをGodot 4、Unity 6、Phaser 3にインポートします。アニメーションのタイミング、アトラス参照、ピボットを修正します。 プロジェクトの規約、インストール済みバージョン、アーキテクチャ、アートスタイル、およびユーザーの明示的な選択が優先されます。 タイミングのみを変更するタスクの場合は、動作しているシートとフォーマットを維持します。スライスと再パッキングはオプションです。 このワークフローは既存のアートを使用し、新しいアニメーションを生成しません。新しいフレームは pixo media generate --sheet <C>x<R> --frames(プロンプトのメディアセクション)から生成され、すでに1つのキャンバス上に書き出されます。

クイックパス

  1. 選択したシートまたはフレームを pixo asset info <path> --json で検査し、現在のクリップ定義を読み取ります。
  2. セルサイズと順序、クリップ範囲、ベースライン、ピボット、ループまたはワンショットのタイミングを確認します。pixo asset frames check <frames...> --json はベースラインとドリフトを自動で測定します。
  3. 直接シートまたはパックのブランチを選択し、操作の実際の出力パスを読み取ります。
  4. ゲームプレイのコリジョンを移動せずに、エンジンの既存のアニメーションオーナーを介して統合します。
  5. 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用の連番PNGpack --format godot-tres入力順序。PNGとTRESは一緒に保持
Phaser用の連番PNGpack --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 を検査し、リソースエラーとスキップされたステップを含む。

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

関連スキル