Communitygithub.com

Sprite-Animation-Pipeline

Vorhandene Sprite-Sheets oder geordnete Einzelbilder importieren und Slicing, Atlas-Referenzen, Pivots oder Timing in Godot 4, Unity 6 oder Phaser 3 korrigieren – nicht geeignet zur Generierung von Grafiken oder Skelett-Rigs.

Was ist Sprite-Animation-Pipeline?

Diese Skill-Anleitung beschreibt eine professionelle Pipeline zum Importieren und Nachbearbeiten von bestehenden Sprite-Animationen in Godot 4, Unity 6 oder Phaser 3. Sie ist speziell auf die Optimierung und Fehlerkorrektur von bereits vorhandener Pixelgrafik ausgerichtet – nicht auf die Generierung neuer Grafiken oder die Arbeit mit Skelett-Rigs. Die Anleitung zeigt, wie man Slicing und Packing von Spritesheets durchführt, Timing und Loop-Verhalten von Animationen anpasst, Atlas-Referenzen korrigiert und Pivots stabilisiert, sodass Figuren in Übergängen zwischen Idle und Lauf nicht wackeln oder verrutschen. Sie unterstützt die Arbeit mit Godot 4 (SprteFrames .tres), Unity 6 (Animation Clips, Sprite Editor, Skript-Slicing) und Phaser 3 (Spritesheets und TexturePacker-Atlanten). Die Pipeline setzt auf die Kommandozeilen-Tools `pixo asset` und `pixo game`, die über die Konfiguration per `PIXO_PROJECT_ID` gesteuert werden. Besonderer Wert wird auf die Bewahrung von Projektkonventionen, der bestehenden Architektur und den expliziten Entscheidungen der Nutzer gelegt. Die Anleitung enthält konkrete Codebeispiele für alle drei Engines, eine Checkliste für den Abschluss sowie eine Tabelle mit typischen Fallstricken und deren korrekter Lösung. Sie ist als Referenz für Entwickler gedacht, die bestehende Animationen in ihren Projekten nachbessern oder in eine andere Engine überführen möchten, ohne die Grafik oder das Gameplay-Collision neu erstellen zu müssen.

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

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Was macht Sprite-Animation-Pipeline?

Importieren Sie geordnete Einzelbilder oder Sheets in Godot 4, Unity 6 oder Phaser 3. Korrigieren Sie Animations-Timing, Atlas-Referenzen und Pivots. Projektkonventionen, installierte Versionen, Architektur, Kunststil und explizite Benutzerentscheidungen haben Vorrang. Behalten Sie ein funktionierendes Sheet und Format bei, wenn die Aufgabe nur das Timing ändert; Slicing und Repacking sind optional. Dieser Workflow verwendet vorhandene Grafiken, anstatt neue Animationen zu generieren; neue Einzelbilder stammen aus pixo media generate --sheet <C>x<R> --frames (dem Medienabschnitt des Prompts), das sie bereits auf einer Leinwand ausgibt.

Schnellweg

  1. Untersuchen Sie das ausgewählte Sheet oder die Einzelbilder mit pixo asset info <path> --json; lesen Sie die aktuellen Clip-Definitionen aus.
  2. Bestätigen Sie Zellgröße und -reihenfolge, Clip-Bereiche, Grundlinie, Pivot und Timing für Loops oder One-Shots. pixo asset frames check <frames...> --json misst die Grundlinie und Abweichung für Sie.
  3. Wählen Sie unten den direkten Sheet- oder Pack-Zweig; lesen Sie die tatsächlichen Ausgabepfade der Operation.
  4. Integrieren Sie über den vorhandenen Animations-Besitzer der Engine, ohne das Gameplay-Collision zu verschieben.
  5. Führen Sie pixo game verify --steps check,build,run --screenshot --json aus, überprüfen Sie Logs und Frames, sehen Sie sich dann interaktiv einen vollständigen Loop und einen One-Shot an.

Befehle setzen PIXO_PROJECT_ID voraus; andernfalls fügen Sie --project <id> hinzu. Pfade und Frame-Anzahlen unten sind Beispiele; Sheets ohne Metadaten identifizieren ihre eigenen Clips nicht. Unity hat keinen run-Schritt oder Screenshot hier: verwenden Sie --steps check,build und sehen Sie Clips im Editor an.

Wählen Sie die kleinste Formatänderung

Eingabe oder AnforderungWählen SieBehalten Sie bei
Funktionierendes normales Sheet, nur Timing-ÄnderungVorhandene SpriteFrames, Unity-Clip oder Phaser-SheetFrame-Bereiche, Textur-Key, gemeinsame Grundlinie
Regelmäßiges Gitter benötigt separate Framespixo asset slice --cell BxH oder --grid CxR mit einem EingabepfadRand, Abstand und erwartete Abdeckung
Frames wackeln, rutschen oder unterscheiden sich in der Größepixo asset frames check, dann frames alignEingabereihenfolge, eine Skalierung für jeden Frame
Geordnete PNGs für Godotpack --format godot-tresEingabereihenfolge; PNG und TRES zusammenhalten
Geordnete PNGs für Phaserpack --format texturepacker-jsonEingabereihenfolge, tatsächliche Deskriptor-Schlüssel
Sheet oder Frames für UnityAls Sprite importieren und in Unity slicen; pack hat keine Unity-AusgabePivot, Pixels Per Unit, vorhandene .meta
Beschnittene Frames mit benutzerdefinierten PivotsVorhandene metadatenbewusste PipelineBeschnitt-Offsets und Pivots; rein bildbasiertes Packen kann sie nicht wiederherstellen

Erfassen Sie nur relevante Vertragsfelder: Leinwand- und Zellgröße, zeilenweise Reihenfolge, Clip-Bereiche, FPS, Frame-Holds, Looping und die Grundlinie für Füße. Gleich große Leinwände mit einem gemeinsamen Anker vermeiden Frame-zu-Frame-Wackeln; undurchsichtige Begrenzungen sind nicht der Pivot.

Slicing und Packing-Anker

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

Verwenden Sie die zurückgegebenen PNG-Pfade aus dem Slice-Bericht; die Zwei-Frame-Pack-Befehle dienen nur zur Veranschaulichung der Reihenfolge. --grid erfordert exakte Teilung nach Rand und Abstand; --cell kann unvollständige Randzellen ungenutzt lassen. Überprüfen Sie die vollständige Abdeckung und Frame-Anzahl. Schließen Sie absichtlich leere Zellen und Frames aus anderen Clips aus. Lesen Sie results, extraOutputs, reportPath, Fehler und originalsPreserved; vorhandene Ziele werden übersprungen.

Packer-Fakten:

  • Der Stamm leitet sich von der ersten Eingabe ab und behält seine relativen Verzeichnisse unter --out bei; lesen Sie Pfade, anstatt zu raten.
  • Ausgaben sind <stamm>.atlas.png plus .atlas.tres oder .atlas.json.
  • Packen kann die räumliche Platzierung neu anordnen, aber Deskriptoren bewahren die Eingabereihenfolge.
  • Keine Rotation, kein Beschnitt, keine Kantenextrusion, keine Clip-Benennung oder benutzerdefinierten Pivots werden generiert.
  • Padding ist transparenter Abstand, keine duplizierten Randpixel.

Frames prüfen und ausrichten

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

Übergeben Sie Frames in Spielreihenfolge (ein Shell-Glob sortiert -10 vor -2; listen Sie sie auf, wenn es zehn oder mehr gibt). frames check schreibt keine Bilder. Pro Frame hat results[].detail die gezeichneten bounds, bottomGap (Zeilen unter den Füßen), feetX (Mitte der untersten Zeilen, die eine geschwungene Waffe nicht bewegt), empty und touchesEdge. summary beurteilt den Satz: baselineSpreadPx (Fußwackeln), feetXSpreadPx (Rutschen), heightDriftPercent, emptyFrames, edgeFrames und einen einfachen Satz pro Problem in issues; ok ist wahr, wenn es keine gibt. Eine Kauer-, Stauch- oder Sprungbewegung ändert die Höhe absichtlich; dieselbe Pose auf unterschiedlichen Höhen ist Modell-Drift.

frames align schreibt jeden Frame auf eine Leinwand <out>/<eingabepfad>.png: Füße auf einer Linie padding über dem unteren Rand, feetX auf der Mittellinie, eine Skalierung für alle, sodass ein Kauer kleiner bleibt als ein Stand. --canvas BxH skaliert jeden Frame um denselben Faktor, damit er passt; ohne ist die Leinwand die kleinste, die alle aufnimmt. --match-height skaliert zuerst jede Zeichnung auf die mittlere Höhe, nur für Drift. --filter nearest hält Pixelgrafik scharf. Seine summary prüft die ausgerichteten Frames erneut. Vorhandene Ausgaben werden übersprungen, wie bei jeder Asset-Operation.

Godot 4: SpriteFrames-Timing

godot-tres gibt SpriteFrames format=3 mit einem looper default-Clip bei 5 FPS aus. Halten Sie PNG und TRES zusammen; die Texturreferenz ist relativ. Importieren Sie neue Bilder über pixo game verify --steps check --json.

Nach Ersetzen des gemeldeten Pfads passt dies einen tatsächlichen Vier-Frame-Clip an:

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) # Beispiel: unten-zentrierter Anker auf einer 32px-Leinwand.
    sprite.play(&"run")

Frame-Dauer 2.0 bedeutet das Doppelte der normalen Frame-Dauer, nicht zwei Sekunden. Verwenden Sie die vereinbarte Grundlinie für den Versatz; halten Sie CharacterBody2D und CollisionShape2D stabil. One-Shot-Clips benötigen loop=false; verbinden Sie animation_finished einmal und steuern Sie den Übergang über die aktive Animation. Referenz: Godot 4.3 SpriteFrames.

Phaser 3: Sheet- oder Atlas-Timing

// preload(), für ein tatsächliches 32px-Sheet:
this.load.spritesheet('player', 'assets/player.png', { frameWidth: 32, frameHeight: 32 });
// create(), mit dem echten Run-Bereich des Projekts:
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-öffentliche Assets laden ohne public/ in der URL. Für Atlanten lädt this.load.atlas(key, pngUrl, jsonUrl) das zurückgegebene Paar. TexturePacker-Hash-Keys sind die Eingabe-Projekt-relative Pfade; lesen Sie sie oder getFrameNames(). Verwenden Sie eine explizite geordnete Liste, wenn Namen keine Reihenfolge codieren.

// orderedNames stammt aus der überprüften Deskriptor-/Clip-Liste.
this.anims.create({ key: 'hero-run', frameRate: 10, repeat: -1,
  frames: orderedNames.map((frame, index) => ({
    key: 'hero-atlas', frame, duration: index === 0 ? 100 : 0,
  })),
}); // Bei 10 FPS hält 100 zusätzliche ms den ersten Frame für insgesamt 200 ms.

Schützen Sie die globale Animationserstellung mit this.anims.exists wie oben; Keys überleben Szenenneustarts. repeat: 0 spielt einmal ab; verwenden Sie einen eigenen One-Shot-Abschluss-Listener. Das Ändern des Ursprungs beeinflusst die Körperplatzierung; überprüfen Sie Größe und Versatz, anstatt Collision zu verschieben, um einen schlechten Pivot zu verstecken. Referenz: Phaser 3.90 animation types.

Unity 6: Importer, Clip und Animator

Unity liest weder godot-tres noch TexturePacker-JSON ohne zusätzliches Paket. Legen Sie das Sheet unter Assets/, setzen Sie dann Texture Type Sprite, Sprite Mode Multiple und die echten Pixels Per Unit. Für Pixelgrafik fügen Sie Point-Filter und keine Komprimierung hinzu. Slicen Sie nach Zellgröße im Sprite Editor mit einem gemeinsamen Pivot wie Bottom. Skriptbasiertes Slicing erfolgt über ISpriteEditorDataProvider aus SpriteDataProviderFactories; TextureImporter.spritesheet ist der alte Pfad. com.unity.2d.aseprite importiert .aseprite-Dateien direkt mit Clips, wenn die Grafik dort beginnt.

Clips können erstellt werden, indem Sie Sprites auswählen und sie im Animationsfenster ablegen, oder per Skript, wenn es viele gibt. Dieses Editor-only-Beispiel erstellt einen Vier-Frame-Loop-Clip und hält den ersten Frame:

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 hat keine zugesicherte Reihenfolge, und hero_10 sortiert vor hero_2 als Text.
        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");
    }
}

Schlüsselzeiten sind Sekunden, daher ist ein Hold eine größere Lücke zwischen Schlüsseln. Setzen Sie stopTime, damit der letzte Frame seine volle Länge erhält.

  • Im Animator sollten Sprite-Übergänge normalerweise Has Exit Time ausgeschaltet und Transition Duration 0 haben, sonst kommt die nächste Pose zu spät.
  • animator.Play(hash) belässt einen Zustand, der bereits läuft, daher ist es sicher, ihn jeden Update aufzurufen. Das erneute Abspielen eines One-Shots benötigt Play(hash, 0, 0f). Hashen Sie Namen einmal mit Animator.StringToHash.
  • Erkennen Sie das Ende eines One-Shots mit einem Animation Event oder überprüfen Sie normalizedTime >= 1, während IsInTransition(0) falsch ist und der Zustands-Hash übereinstimmt. Ein Übergang kann sonst den alten Zustand melden.
  • Platzieren Sie Animator und SpriteRenderer auf einem Kind, mit dem Rigidbody2D und Collider auf dem Root, und schalten Sie Apply Root Motion aus. flipX spiegelt weder Collider noch Kind-Objekte und spiegelt um den Pivot, daher springt ein außermittiger Pivot.
  • Enge Sprite-Meshes können Effekte abschneiden, die über den Rahmen gezeichnet werden; verwenden Sie Full Rect, wenn ein Shader über die Kontur hinaus sampelt.
  • Ein Sprite Atlas fasst separat importierte Frames zusammen. Geben Sie ihm Padding und schalten Sie Tight Packing und Allow Rotation für Pixelgrafik aus.

Fallstricke: falsch → richtig

FalschRichtig, und warum
Ungepolsterte Dateinamen lexikografisch sortierenExplizite Reihenfolge; frame-10 kommt sonst vor frame-2
Jeden Frame unabhängig beschneidenLeinwand oder gültige Offsets behalten, sodass Füße stehen bleiben
Gepackte Basisnamen ratenDeskriptor-Schlüssel und zurückgegebene Ausgabepfade lesen
Dasselbe Dauergerät in jeder Engine verwendenGodot verwendet relative Multiplikatoren, Phaser-Frame-Dauer addiert Millisekunden, Unity-Schlüssel sind Sekunden
play(key) jeden Update aufrufenplay(key, true) vermeidet Neustart eines bereits aktiven Clips
Visuelle Clip-Geschwindigkeit implizit Schaden oder Physik ändern lassenGameplay-Timing maßgeblich halten, es sei denn, explizit gekoppelt

Erledigt, wenn

  • Tatsächliche Frame-Anzahl, Frame-Reihenfolge, Clip-Timing, Looping und One-Shot-Verhalten der Anforderung entsprechen.
  • Füße und Pivots bleiben stabil durch Übergänge zwischen Idle und Run, Spiegelung und Neustart; pixo asset frames check meldet ok für jeden Zustand, oder seine verbleibenden Probleme sind beabsichtigt.
  • Atlas-Referenzen und Ladepfade sind echt; visuelle Änderungen erhalten das Collision-Verhalten.
  • Verwenden Sie pixo game run <projectId> --json oder den Editor bei Unity, um vollständige Loops und One-Shot-Abschluss zu beobachten; ein Standbild kann Timing nicht beweisen. Melden Sie getestete Timings und ungelöste Probleme.
  • Überprüfen Sie pixo game verify --steps check,build,run --screenshot --json, einschließlich Ressourcenfehlern und übersprungener Schritte.

Individual skills in this repo

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

Verwandte Skills