Communitygithub.com

스프라이트 애니메이션 파이프라인

Godot 4, Unity 6 또는 Phaser 3에서 기존 스프라이트 시트나 순서가 지정된 프레임을 가져와 슬라이싱, 아틀라스 참조, 피벗 또는 타이밍을 수정합니다. 아트를 생성하거나 스켈레탈 리그를 만드는 용도는 아닙니다.

스프라이트 애니메이션 파이프라인란 무엇인가요?

이 스킬은 Godot 4, Unity 6, Phaser 3 게임 엔진에서 기존 스프라이트 시트 또는 순서가 지정된 PNG 프레임을 가져와 애니메이션 클립을 설정하고 세부 사항을 조정하는 파이프라인을 제공합니다. 아트 생성이나 스켈레탈 애니메이션이 아닌 기존 에셋을 이용한 애니메이션 타이밍, 피벗, 아틀라스 참조 수정에 초점을 맞춥니다. `pixo asset` 명령어를 사용하여 스프라이트 시트를 슬라이싱하거나, 프레임 정렬 상태를 확인 및 정렬하거나, 엔진별 포맷(godot-tres, texturepacker-json)으로 패킹할 수 있습니다. 각 엔진(Godot 4의 SpriteFrames, Unity 6의 AnimationClip, Phaser 3의 animation.create)에 맞는 코드 예제와 함께 프레임 지속 시간, 루프 설정, 원샷 클립 처리 방법을 구체적으로 안내합니다. 사용자 프로젝트 규칙과 기존 아트 스타일을 우선시하며, 워크플로우 변경이 충돌이나 게임플레이에 영향을 주지 않도록 검증(`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. 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입력 순서, 모든 프레임에 하나의 스케일
Godot용 순서가 지정된 PNGpack --format godot-tres입력 순서, PNG와 TRES를 함께 유지
Phaser용 순서가 지정된 PNGpack --format texturepacker-json입력 순서, 실제 설명자 키
Unity용 시트 또는 프레임Sprite로 가져와 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 경로를 사용하세요. 두 프레임 팩 명령어는 순서를 설명하기 위한 예시입니다. --grid는 여백과 간격 후 정확한 분할이 필요합니다. --cell은 불완전한 가장자리 셀을 사용하지 않을 수 있습니다. 전체 커버리지와 프레임 수를 확인하세요. 다른 클립의 빈 셀과 프레임을 의도적으로 제외하세요. results, extraOutputs, reportPath, 실패 및 originalsPreserved를 읽으세요. 기존 대상은 건너뜁니다.

패커 팩트:

  • Stem은 첫 번째 입력에서 파생되며 --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은 각 프레임을 <out>/<input path>.png에 하나의 캔버스로 기록합니다. 발은 바닥에서 padding 위의 한 줄에, feetX는 중심선에, 모든 프레임에 하나의 스케일을 적용하여 움츠림이 서 있는 것보다 짧게 유지됩니다. --canvas WxH는 모든 프레임을 동일한 계수로 스케일하여 맞춥니다. 없으면 캔버스는 모든 프레임을 담을 수 있는 가장 작은 크기입니다. --match-height는 먼저 각 그림을 중간 높이로 스케일하여 드리프트만 수정합니다. --filter nearest는 픽셀 아트를 선명하게 유지합니다. summary는 정렬된 프레임을 다시 확인합니다. 모든 에셋 작업과 마찬가지로 기존 출력은 건너뜁니다.

Godot 4: SpriteFrames 타이밍

godot-tres는 5 FPS에서 루프 default 클립을 사용하여 SpriteFrames 포맷=3을 출력합니다. 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초가 아닙니다. 오프셋에 대해 합의된 기준선을 사용하세요. 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은 한 번 재생합니다. 소유한 원샷 완료 리스너를 사용하세요. 원점 변경은 바디 배치에 영향을 줍니다. 잘못된 피벗을 숨기기 위해 충돌을 이동하는 대신 크기와 오프셋을 검사하세요. 참조: 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)는 이미 활성화된 클립을 다시 시작하지 않음
시각적 클립 속도가 데미지나 물리를 암시적으로 변경하도록 함명시적으로 결합되지 않는 한 게임플레이 타이밍을 권위적으로 유지

완료 조건

  • 실제 프레임 수, 프레임 순서, 클립 타이밍, 루핑 및 원샷 동작이 요청과 일치합니다.
  • 발과 피벗이 idle과 run 사이의 트랜지션, 미러링 및 재시작을 통해 안정적으로 유지됩니다. pixo asset frames check는 각 상태에 대해 ok를 보고하거나, 남은 문제가 의도적입니다.
  • 아틀라스 참조와 로드 경로가 실제입니다. 시각적 변경은 충돌 동작을 보존합니다.
  • pixo game run <projectId> --json 또는 Unity의 Editor를 사용하여 완전한 루프와 원샷 완료를 시청합니다. 정지 이미지는 타이밍을 증명할 수 없습니다. 테스트된 타이밍과 해결되지 않은 문제를 보고합니다.
  • 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.

관련 스킬