Pipeline de animación de sprites
Importa fotogramas ordenados o hojas en Godot 4, Unity 6 o Phaser 3. Corrige la temporización de la animación, las referencias de atlas y los pivotes.
Tienen prioridad las convenciones del proyecto, las versiones instaladas, la arquitectura, el estilo artístico y las elecciones explícitas del usuario.
Conserva una hoja y un formato funcionales cuando la tarea solo cambia la temporización; el cortado y el reempaquetado son opcionales.
Este flujo de trabajo utiliza arte existente en lugar de generar nuevas animaciones; los nuevos fotogramas provienen de pixo media generate --sheet <C>x<R> --frames (la sección de medios del prompt), que los escribe ya en un mismo lienzo.
Ruta rápida
- Inspecciona la hoja o los fotogramas seleccionados con
pixo asset info <ruta> --json; lee las definiciones de clips actuales. - Confirma el tamaño y orden de las celdas, los rangos de clips, la línea de base, el pivote y la temporización para bucles o de una sola toma.
pixo asset frames check <fotogramas...> --jsonmide la línea de base y la deriva por ti. - Elige la rama directa de hoja o de empaquetado a continuación; lee las rutas de salida reales de la operación.
- Integra mediante el propietario de animación existente del motor sin mover la colisión de gameplay.
- Ejecuta
pixo game verify --steps check,build,run --screenshot --json, inspecciona los registros y los fotogramas, y luego observa un bucle completo y una toma única de forma interactiva.
Los comandos asumen PIXO_PROJECT_ID; en caso contrario, añade --project <id>.
Las rutas y los recuentos de fotogramas que aparecen a continuación son ejemplos; las hojas sin metadatos no identifican sus propios clips.
Unity no tiene paso run ni captura de pantalla aquí: usa --steps check,build y mira los clips en el Editor.
Elige el cambio de formato más pequeño
| Entrada o solicitud | Elige | Conserva |
|---|---|---|
| Hoja regular funcional, cambio solo de temporización | SpriteFrames existentes, clip de Unity o hoja de Phaser | Rangos de fotogramas, clave de textura, línea de base compartida |
| Cuadrícula regular necesita fotogramas separados | pixo asset slice --cell AnxAl o --grid CxR con una ruta de entrada | Margen, espaciado y cobertura esperada |
| Los fotogramas tiemblan, se deslizan o difieren en tamaño | pixo asset frames check, luego frames align | Orden de entrada, una escala para cada fotograma |
| PNGs ordenados para Godot | pack --format godot-tres | Orden de entrada; mantener PNG y TRES juntos |
| PNGs ordenados para Phaser | pack --format texturepacker-json | Orden de entrada, claves de descriptor reales |
| Hoja o fotogramas para Unity | Importar como Sprite y cortar en Unity; pack no tiene salida Unity | Pivote, Píxeles por Unidad, .meta existente |
| Fotogramas recortados con pivotes personalizados | Pipeline existente con metadatos | Desplazamientos de recorte y pivotes; el empaquetado solo de imágenes no puede recuperarlos |
Registra solo los campos contractuales relevantes: tamaño del lienzo y de la celda, orden por filas, rangos de clips, FPS, retenciones de fotogramas, bucle y la línea de base para los pies. Los lienzos del mismo tamaño con un anclaje compartido evitan el bamboleo entre fotogramas; los límites opacos no son el pivote.
Anclajes de cortado y empaquetado
pixo asset slice assets/public/player.png --cell 32x32 --out derived/player-frames --dry-run --json
pixo asset slice assets/public/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 sprites/public/run/frame-0000.png sprites/public/run/frame-0001.png --format texturepacker-json --padding 1 --out public/atlases/run --json
Usa las rutas PNG devueltas en el informe de cortado; los comandos de empaquetado de dos fotogramas solo ilustran el orden.
--grid requiere división exacta después del margen y el espaciado; --cell puede dejar sin usar celdas de borde incompletas.
Comprueba la cobertura total y el recuento de fotogramas. Excluye deliberadamente celdas vacías y fotogramas de otros clips.
Lee results, extraOutputs, reportPath, los fallos y originalsPreserved; los destinos existentes se omiten.
Datos del empaquetador:
- La raíz deriva de la primera entrada y conserva sus directorios relativos por debajo de
--out; lee las rutas en lugar de adivinarlas. - Las salidas son
<raíz>.atlas.pngmás.atlas.treso.atlas.json. - El empaquetado puede reorganizar la colocación espacial, pero los descriptores conservan el orden de entrada.
- No se generan rotación, recorte, extrusión de bordes, nombres de clips ni pivotes personalizados.
- El relleno es separación transparente, no píxeles de borde duplicados.
Comprobar y alinear fotogramas
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
Pasa los fotogramas en orden de reproducción (un glob del shell ordena -10 antes que -2; enuméralos cuando haya diez o más).
frames check no escribe imágenes. Por fotograma, results[].detail tiene los bounds dibujados, bottomGap (filas debajo de los pies), feetX (centro de las filas más bajas, que un arma balanceada no mueve), empty y touchesEdge.
summary juzga el conjunto: baselineSpreadPx (bamboleo de pies), feetXSpreadPx (deslizamiento), heightDriftPercent, emptyFrames, edgeFrames y una frase simple por problema en issues; ok es verdadero cuando no hay ninguno.
Una cuclilla, un aplastamiento o un salto cambian la altura a propósito; la misma pose a diferentes alturas es deriva del modelo.
frames align escribe cada fotograma en <out>/<ruta de entrada>.png sobre un lienzo: los pies en una línea padding por encima del borde inferior, feetX en la línea central, una escala para todos para que una cuclilla siga siendo más baja que una postura erguida.
--canvas AnxAl escala cada fotograma por el mismo factor para que quepa; sin él, el lienzo es el más pequeño que los contiene a todos.
--match-height primero escala cada dibujo a la altura mediana, solo para la deriva. --filter nearest mantiene el arte de píxel nítido.
Su summary vuelve a comprobar los fotogramas alineados. Las salidas existentes se omiten, como en toda operación de activos.
Godot 4: temporización de SpriteFrames
godot-tres emite SpriteFrames formato=3 con un clip default en bucle a 5 FPS.
Mantén PNG y TRES juntos; la referencia de textura es relativa. Importa nuevas imágenes mediante pixo game verify --steps check --json.
Después de sustituir la ruta notificada, esto adapta un clip real de cuatro fotogramas:
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("Se esperaban cuatro fotogramas de carrera")
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) # Ejemplo: anclaje centro-inferior en un lienzo de 32px.
sprite.play(&"run")
La duración del fotograma 2.0 significa el doble de la duración normal del fotograma, no dos segundos.
Usa la línea de base acordada para el desplazamiento; mantén estables CharacterBody2D y CollisionShape2D.
Los clips de una sola toma necesitan loop=false; conecta animation_finished una vez y controla la transición mediante la animación activa.
Referencia: Godot 4.3 SpriteFrames.
Phaser 3: temporización de hoja o atlas
// preload(), para una hoja real de 32px:
this.load.spritesheet('player', 'assets/player.png', { frameWidth: 32, frameHeight: 32 });
// create(), con el rango de carrera real del proyecto:
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);
Los activos públicos de Vite se cargan sin public/ en la URL.
Para atlas, this.load.atlas(key, pngUrl, jsonUrl) carga el par devuelto.
Las claves hash de TexturePacker son las rutas relativas al proyecto de entrada; léelas o usa getFrameNames().
Usa una lista ordenada explícita cuando los nombres no codifiquen el orden.
// orderedNames proviene de la lista de descriptores/clips revisada.
this.anims.create({ key: 'hero-run', frameRate: 10, repeat: -1,
frames: orderedNames.map((frame, index) => ({
key: 'hero-atlas', frame, duration: index === 0 ? 100 : 0,
})),
}); // A 10 FPS, 100 ms extra mantienen el primer fotograma durante 200 ms en total.
Protege la creación de animaciones globales con this.anims.exists como arriba; las claves sobreviven a los reinicios de Escena.
repeat: 0 se reproduce una vez; usa un listener de finalización de toma única propio.
Cambiar el origen afecta la colocación del cuerpo; inspecciona el tamaño y el desplazamiento en lugar de mover la colisión para ocultar un pivote malo.
Referencia: Tipos de animación de Phaser 3.90.
Unity 6: importador, clip y Animator
Unity no lee ni godot-tres ni JSON de TexturePacker sin un paquete adicional. Coloca la hoja en Assets/, luego establece Texture Type Sprite, Sprite Mode Multiple y los Pixels Per Unit reales. Para arte de píxel, añade filtro Point y sin compresión. Corta por tamaño de celda en el Sprite Editor, con un pivote compartido como Bottom. El cortado mediante script pasa por ISpriteEditorDataProvider de SpriteDataProviderFactories; TextureImporter.spritesheet es la ruta antigua. com.unity.2d.aseprite importa archivos .aseprite directamente, con clips, cuando el arte comienza allí.
Los clips se pueden hacer seleccionando sprites y soltándolos en la ventana Animation, o desde un script cuando hay muchos. Este ejemplo solo para Editor construye un clip en bucle de cuatro fotogramas y mantiene el primer fotograma:
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 no tiene orden prometido, y hero_10 se ordena antes que hero_2 como texto.
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("Se esperaban cuatro fotogramas de carrera");
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");
}
}
Los tiempos clave están en segundos, por lo que una retención es un espacio mayor entre claves. Establece stopTime para que el último fotograma tenga su duración completa.
- En el Animator, las transiciones de sprite generalmente quieren Has Exit Time desactivado y Transition Duration 0, o la pose siguiente llega tarde.
animator.Play(hash)deja un estado que ya se está reproduciendo solo, por lo que llamarlo cada actualización es seguro. Volver a reproducir una toma única necesitaPlay(hash, 0, 0f). Hashea los nombres una vez conAnimator.StringToHash.- Detecta el final de una toma única con un Animation Event, o comprueba
normalizedTime >= 1mientrasIsInTransition(0)es falso y el hash del estado coincide. Una transición puede, de lo contrario, informar del estado anterior. - Coloca el Animator y el SpriteRenderer en un hijo, con el Rigidbody2D y el collider en la raíz, y desactiva Apply Root Motion.
flipXno voltea colliders ni objetos hijo, y refleja alrededor del pivote, por lo que un pivote descentrado salta. - Las mallas de sprites ajustadas pueden recortar efectos dibujados sobre el fotograma; usa Full Rect cuando un sombreador muestree más allá del contorno.
- Un Sprite Atlas agrupa por lotes fotogramas importados por separado. Dale relleno y desactiva Tight Packing y Allow Rotation para arte de píxel.
Errores comunes: incorrecto → correcto
| Incorrecto | Correcto, y por qué |
|---|---|
| Ordenar nombres de archivo sin relleno lexicográficamente | Orden explícito; frame-10 precede a frame-2 en caso contrario |
| Recortar cada fotograma independientemente | Mantener el lienzo o los desplazamientos válidos para que los pies permanezcan plantados |
| Adivinar nombres base empaquetados | Leer las claves del descriptor y las rutas de salida devueltas |
| Usar la misma unidad de duración en cada motor | Godot usa multiplicadores relativos, Phaser duración de fotograma añade milisegundos, las claves de Unity están en segundos |
Llamar a play(key) cada actualización | play(key, true) evita reiniciar un clip ya activo |
| Dejar que la velocidad visual del clip cambie el daño o la física implícitamente | Mantener la temporización del juego como autoridad a menos que esté acoplada explícitamente |
Hecho cuando
- El recuento real de fotogramas, el orden de los fotogramas, la temporización del clip, el bucle y el comportamiento de una sola toma coinciden con la solicitud.
- Los pies y los pivotes permanecen estables a través de transiciones entre reposo y carrera, reflejo y reinicio;
pixo asset frames checkinformaokpara cada estado, o sus problemas restantes son deliberados. - Las referencias de atlas y las rutas de carga son reales; los cambios visuales preservan el comportamiento de colisión.
- Usa
pixo game run <projectId> --json, o el Editor en Unity, para ver bucles completos y la finalización de una sola toma; una imagen fija no puede probar la temporización. Informa las temporizaciones probadas y los problemas no resueltos. - Inspecciona
pixo game verify --steps check,build,run --screenshot --json, incluidos los errores de recursos y los pasos omitidos.