Guía de Animación
Estándar de producción para el equipo de animación y captura de movimiento
Cómo leer esta guía
El framework de gameplay ya está construido y compilado. Eso cambia la naturaleza del trabajo de animación: no estamos diseñando un sistema, estamos entregando contra un contrato que ya existe.
El C++ calcula y publica variables. El Animation Blueprint las lee y las convierte en pose. El Event Graph del ABP queda VACÍO. El AnimGraph nunca castea al personaje ni llama a componentes: lee las variables de
USHAnimInstancey punto.
Esto no es dogma: es lo que permite cambiar la técnica de animación sin tocar gameplay, y cambiar gameplay sin romper animación. Cualquier entrega que exija lógica en el Event Graph del ABP está mal planteada y hay que rehacerla.
Las Partes 0 y 1 son de lectura obligatoria antes de capturar el primer plano. El resto se consulta sobre la marcha.
Parte 0 · El contrato: lo que el C++ ya te da
Estas variables existen hoy en USHAnimInstance y se rellenan solas cada frame. Están disponibles en cualquier ABP que herede de SHAnimInstance. El animador no tiene que pedirlas ni programarlas: arrastra la variable y la conecta.
Locomoción
| Variable | Tipo | Rango | Qué es | Uso previsto |
|---|---|---|---|---|
GroundSpeed | float | 0 … RunSpeed | Módulo 2D de la velocidad (cm/s) | Eje Y del Blend Space |
MovementDirection | float | −180 … 180 | Ángulo de la velocidad respecto al actor | Eje X del Blend Space |
bIsMoving | bool | — | GroundSpeed > 3 | Transición Idle ↔ Locomoción |
bIsCrouching | bool | — | Agachado | Rama de agachado |
bIsInAir | bool | — | Cayendo | Rama de salto/caída |
bIsWading | bool | — | Vadeando agua somera | Capa de paso pesado |
YawDeltaRate | float | grados/s, ± | Ritmo de giro suavizado | Lean en giros |
Estados de combate
| Variable | Tipo | Qué es |
|---|---|---|
bIsAiming | bool | Apuntando (doctrina RE: disparar EXIGE apuntar) |
bIsDead | bool | Muerto |
bIsStaggered | bool | Aplomo roto |
bIsGrabbed | bool | Siendo agarrado (víctima) |
bIsGrabbing | bool | Agarrando (agresor) |
bIsReloading | bool | Recargando |
AimPitch | float | −90 … 90 · eje vertical del Aim Offset |
AimYaw | float | −180 … 180 · eje horizontal del Aim Offset |
CurrentWeaponOverlay | GameplayTag | Weapon.Overlay.*, vacío = desarmado |
Turn-in-place por ángulo acumulado
| Variable | Tipo | Qué es | Dónde se conecta |
|---|---|---|---|
RootYawOffset | float | −180 … 180 · cuánto está girada la malla respecto al actor | Pin Yaw de Rotate Root Bone |
bShouldTurnInPlace | bool | Hay un giro en curso | Entrada del estado TurnInPlace |
TurnInPlaceAngle | float | Ángulo del giro. Positivo = derecha | Selecciona el clip (90 izq / 90 der / 180) |
Reacción al impacto — nivel micro (consumo exclusivo de la capa IK)
| Variable | Tipo | Qué es |
|---|---|---|
HitReactionLocalDirection | FVector | Dirección del empuje en espacio local del actor |
HitReactionStrength | float | 0…1 con decaimiento de resorte. 0 = sin reacción |
LastHitBone | FName | Hueso golpeado — la capa IK decide qué cadena empujar |
Offset del efector = HitReactionLocalDirection × HitReactionStrength × MaxOffset(cm)
Aplicada con Dragon IK sobre la cadena que contenga LastHitBone (fallback: spine/head).
Variación por instancia (anti-clones)
| Variable | Rango | Dónde se conecta |
|---|---|---|
AnimPhaseOffset | 0 … 1 | Pin Start Position del Sequence Player del idle |
AnimPlayRateScale | ~0.93 … 1.07 | Pin Play Rate de idle y locomoción — JAMÁS de ataques |
bMirrorPose | bool | Pin del nodo Mirror |
AnimVariantIndex | 0 … N−1 | Blend Poses by Int entre idles alternativos |
Regla dura. AnimPlayRateScale nunca toca un ataque. Las ventanas de daño (SHAnimNotifyState_DamageWindow) y el cooldown de token del Enemy Director asumen duraciones fijas. Un enemigo al ritmo 0.93 retiene su token más tiempo del que el Director espera y rompe la coreografía de la manada.
Lo que NO existe todavía
Si una entrega necesita algo que no está en las tablas de arriba, hay que pedirlo antes de capturar, no después. Añadir una variable al C++ es trabajo de minutos; rehacer una jornada de captura no lo es. Candidatos habituales:
- Pendiente del terreno (lean en rampas).
- Velocidad vertical (diferenciar subida de caída en el salto).
- Distancia al suelo (anticipar el aterrizaje).
- Curva de distancia recorrida (distance matching: el estándar más alto contra el deslizamiento en arranques y frenadas; requiere C++ y captura específica).
Parte 1 · Captura y limpieza: especificación de entrega
1.1 Esqueleto y retarget
- Un solo esqueleto: CC5. Todo personaje humanoide comparte esqueleto. No se abre uno nuevo sin aprobación: rompe la reutilización de montages, el
BoneToBodyPartdel Data Asset y la posibilidad de usar Child Anim Blueprints. - La bind pose de entrega debe coincidir con la de CC5 (A-pose de CC5, no T-pose genérica).
- El retarget de librerías externas se hace con IK Rig + IK Retargeter, nunca con el retarget legacy por nombre de hueso.
- Criaturas no humanoides llevan esqueleto propio y ABP propio: es la única excepción aceptable.
1.2 Frecuencia de captura y entrega
| Tipo de clip | Captura | Entrega en engine |
|---|---|---|
| Locomoción, idles, esperas | 60 fps | 30 fps |
| Ataques, esquivas, staggers | 120 fps | 60 fps |
| Muertes, derribos, takedowns | 120 fps | 60 fps |
| Cinemáticas de agarre | 120 fps | 60 fps |
El motivo del 120 en combate: una ventana de daño puede durar 4 frames. A 30 fps eso son 0.13 s con una resolución temporal tan gruesa que el ajuste fino se vuelve imposible, y el impacto se lee «flojo» sin que nadie sepa por qué.
1.3 Root motion — la política, clip por clip
Esta es la decisión que más bugs causa si se toma mal.
| Familia | Root motion | Por qué |
|---|---|---|
| Locomoción (walk/run/strafe/crouch) | NO · in-place | El CharacterMovementComponent y el NavMesh mueven al actor. Root motion pelearía con la navegación de la IA |
| Idles y esperas | NO | — |
| Turn-in-place | NO · curva | Lo resuelve la curva TurnYawWeight (ver 3.4) |
| Ataques con desplazamiento | NO + Motion Warping | El notify de Warp ya está previsto en FSHAttackDef |
Derribo (KnockdownMontage) | SÍ | Caída y levantada deben desplazar el cuerpo de verdad |
Agarre (GrabMontage) | SÍ | Agresor y víctima deben quedar alineados |
Takedown (TakedownVictimMontage) | SÍ | Par sincronizado con el montage de la jugadora |
| Muertes no-ragdoll | SÍ | — |
| Hit reactions aditivas | NUNCA | Una aditiva con root motion corrompe la posición |
Entrega. El root bone debe existir, estar en el origen y con rotación identidad en el frame 0 de todo clip in-place. Cualquier deriva del root en un clip in-place es un rechazo automático.
1.4 Bucles
- Un clip que cicla no duplica el primer frame al final. El último frame debe ser el fotograma anterior al frame 0, no una copia. Duplicarlo produce un tirón de un frame en cada vuelta — el defecto más común y más difícil de diagnosticar ya en engine.
- Los ciclos de locomoción se entregan con el mismo número de frames por pie y con el contacto del talón derecho en frame 0. Así se pueden sincronizar clips distintos en el mismo Blend Space sin que los pies se peleen.
- Idles: mínimo 4 segundos, sin pose de descanso perfectamente simétrica (la simetría delata el bucle). Por debajo de 3 s el ojo detecta la repetición aunque haya desfase por instancia.
1.5 Pies y contacto
- Contacto de suelo en Z = 0. Nada de personajes flotando 2 cm que luego se «arreglan» moviendo el mesh en el Blueprint.
- Sin deslizamiento de pies. La velocidad de avance del clip debe coincidir con la velocidad de gameplay a la que se va a reproducir. Un ciclo capturado a 1.4 m/s reproducido a 2.0 m/s patina y se ve barato, por muy buena que sea la captura.
- Los sockets de pie deben existir con nombre estable para el notify de pisada (
USHAnimNotify_FootstepleeFootSocketNamey traza al suelo desde ahí).
1.6 Nomenclatura
AS_<Especie>_<Familia>_<Variante> Animation Sequence
AS_Penitent_Walk_Fwd · AS_Penitent_Idle_A · AS_Penitent_Attack_SwipeR
AM_<Especie>_<Familia>_<Variante> Animation Montage
AM_Penitent_Attack_SwipeR · AM_Penitent_Stagger
BS_<Especie>_<Proposito> Blend Space
AO_<Especie>_<Proposito> Aim Offset
ABP_<Especie> Animation Blueprint
MDT_<Esqueleto> Mirror Data Table
Sin tildes ni eñes en nombres de asset. La familia va antes que la variante para que el Content Browser agrupe solo.
Parte 2 · Blend Spaces
2.1 Cuántos y de qué tipo
Un error caro y frecuente es meter todo en un solo Blend Space gigante. La arquitectura correcta reparte:
| Blend Space | Tipo | Ejes | Quién lo usa |
|---|---|---|---|
BS_<X>_Locomotion | 2D | Direction × Speed | Todos los bípedos que se desplazan |
AO_<X>_Aim | Aim Offset (aditivo) | Pitch (y Yaw si aplica) | Jugadora y enemigos con arma |
BS_<X>_Crawl | 1D o 2D | Speed (y Direction) | El rastrero (mutación de amputación) |
NO se hace Blend Space para: staggers, ataques, muertes, agarres, esquivas, reacciones ni giros. Todo eso son Montages o clips discretos.
2.2 BS_<X>_Locomotion — especificación por eje
Eje horizontal — Direction
- Nombre:
Direction· Rango: −180 a 180 - Divisiones de rejilla: 8 (pasos de 45°, para que las diagonales caigan en rejilla)
- Se alimenta de
MovementDirection - Interpolation Time: 0.15 s. Más bajo produce latigazos al cambiar de dirección; más alto produce esa sensación de «coche patinando» que delata el sistema
Eje vertical — Speed
- Nombre:
Speed· Rango: 0 aRunSpeeddel Data Asset (por defecto 450; los enemigos suelen ir a 150–250) - Divisiones de rejilla: elegir para que
WalkSpeedyRunSpeedcaigan exactamente en una línea. Con rango 0–450, usar 9 divisiones (pasos de 50) permite colocar muestras en 0, 200 y 450 - Se alimenta de
GroundSpeed· Interpolation Time: 0.10 s
La regla de oro del eje Speed. Cada muestra se coloca en la coordenada a la que fue capturada, no donde queda bonita. Si el ciclo de caminar se capturó a 200 cm/s, va en Y=200. Colocarlo en otro sitio garantiza deslizamiento de pies. Si hay discrepancia entre el clip y el
WalkSpeeddel Data Asset, se cambia el dato o se recaptura — no se miente en el eje.
2.3 Cuántas muestras
Dos niveles de acabado. Elegir por arquetipo, no por presupuesto.
Nivel sólido — 4 direcciones
Para enemigos que rara vez orbitan: penitentes, carroñeros, cualquier cosa que camine hacia ti.
| Fila | Muestras |
|---|---|
| Speed = WalkSpeed | Fwd (0°), Right (90°), Left (−90°), Back (180°) y Back otra vez en (−180°) |
| Speed = RunSpeed | los mismos 4 + la repetición de Back |
= 8 clips únicos, 10 muestras colocadas.
Nivel AA — 8 direcciones
Para la jugadora y para cualquier enemigo con rol de Flanqueador o Acosador, que sí orbita. Filas a 0°, 45°, 90°, 135°, 180°, −135°, −90°, −45° y 180° repetido en −180°, en ambas velocidades.
= 16 clips únicos, 18 muestras colocadas.
El error del borde (crítico). El eje va de −180 a 180 y esos dos extremos son el mismo ángulo físico. Si solo colocas el clip de caminar hacia atrás en +180, todo el lado negativo del blend space interpola hacia el vacío y el personaje hace un giro fantasma al cruzar por detrás. El clip de Back se coloca DOS veces: en +180 y en −180. Es un asset, dos muestras.
La fila Speed = 0 se deja vacía. El idle no vive en el Blend Space: vive en su propio estado de la máquina de estados.
Descripción clip por clip: el Anexo A desarrolla las 10 y las 18 muestras una a una — qué contiene cada animación, cómo se captura y qué error evita. Es la sección que hay que pasarle al animador junto con ésta. Y ojo con los Sync Markers: son requisito de entrega.
2.4 AO_<X>_Aim — Aim Offset
- Tipo de asset: Aim Offset, no Blend Space normal.
- Las poses deben ser aditivas, con
Additive Anim Type = Mesh Spacey base pose = la pose de idle apuntando. - Con
bDisableWhileAiming = true(defecto): un solo eje (Pitch), rango −90 a 90, alimentado porAimPitch. 3 poses mínimo (arriba/centro/abajo), 5 para AA. - Con
bDisableWhileAiming = false: hace falta también eje horizontal alimentado porAimYaw. 3×3 = 9 poses mínimo, 5×3 = 15 para AA.
2.5 Overlays de arma
CurrentWeaponOverlay es un GameplayTag. La forma correcta de consumirlo no es duplicar el Blend Space de locomoción por arma — eso multiplica los assets por el número de armas y hace la manutención imposible.
La forma correcta: una pose aditiva de tren superior por arma, mezclada con Layered blend per bone sobre la locomoción base, con el filtro a partir de spine_01.
- Entrega por arma: 1 pose aditiva (un solo frame basta) + opcionalmente 1 ciclo aditivo de caminar si el balanceo de brazos debe cambiar.
- La selección entre poses se hace con un
Blend Poses by...sobre el tag, en el AnimGraph.
Parte 3 · Animation Blueprint y máquina de estados
3.1 Arquitectura del AnimGraph — el orden importa
El orden de las capas no es estético: determina qué puede sobreescribir a qué. Este es el orden canónico del proyecto:
1. Maquina de estados de LOCOMOCION (base pose)
v
2. Nodo ROTATE ROOT BONE <- RootYawOffset (turn in place)
v
3. Nodo MIRROR <- bMirrorPose
v (antes de los slots: no queremos ataques espejados)
4. Layered blend per bone: OVERLAY ARMA <- CurrentWeaponOverlay (aditivo, spine_01 arriba)
v
5. Slot 'UpperBody' <- disparo, recarga
v
6. Slot 'FullBody' <- ataques, stagger, derribo, agarre, muerte, takedown
v
7. Apply Additive: slot 'HitReactAdditive' <- reacciones direccionales de nivel medio
v
8. Aim Offset (aditivo) <- AimPitch / AimYaw
v
9. CAPA IK (Dragon IK) <- HitReactionLocalDirection / Strength / LastHitBone
v
10. Output Pose
Justificaciones que no son negociables:
- Rotate Root Bone va antes que todo lo demás. Es una rotación de la pose entera; si va después de los slots, rota también los ataques y desalinea el barrido respecto a lo que el código evalúa.
- El Mirror va antes de los slots. Si va al final, espeja también los ataques y las reacciones.
- La capa IK va la última. Es un post-proceso: empuja huesos sobre la pose ya resuelta. Si va antes de los slots, un montage la pisa y el feedback de impacto desaparece justo en los golpes que más importan.
- El Aim Offset va después de los slots de cuerpo completo para que un stagger no quede apuntando al cielo.
3.2 La máquina de estados de locomoción
| Estado | Contenido | Entra cuando |
|---|---|---|
Idle | Sequence Player (o Blend Poses by Int si hay variantes) | !bIsMoving |
Locomotion | BS_<X>_Locomotion | bIsMoving |
TurnInPlace | Clips de giro discretos (ver 3.4) | bShouldTurnInPlace |
Wading | Ciclo de vadeo o aditiva de agua | bIsWading |
Death | Clip de muerte | bIsDead (solo si la especie no usa ragdoll puro) |
Estados adicionales de la jugadora: Crouch, Jump, Fall, Land.
Lo que NO va en la máquina de estados: stagger, derribo, ataques, agarre, esquiva, takedown, enrage, transiciones de fase. Todo eso llega por Montage en slot y no necesita estado. Meter un estado por cada uno convierte la máquina en un plato de espagueti y duplica lógica que el C++ ya resuelve.
El motivo técnico: el C++ dispara esos montages con PlayAnimMontage(...), con timers de red de seguridad ligados a la duración devuelta por el montage. Si además hubiera un estado compitiendo, habría dos fuentes de verdad para «cuándo termina el stagger» — y ya existe una salida única (EndStaggerState).
3.3 El estado Idle y la variación por instancia
El nodo del idle es el único que consume las cuatro variables anti-clones:
- Start Position ←
AnimPhaseOffset - Play Rate ←
AnimPlayRateScale - Si
IdleVariantCount > 1: Blend Poses by Int ←AnimVariantIndex, con un Sequence Player por variante, cada uno con sus propios Start Position y Play Rate.
Cuántas variantes merecen la pena: dos, si son de silueta distinta (uno encorvado, otro con la cabeza ladeada). A la distancia a la que el jugador ve una manada, lee postura, no detalle facial. Un tercer idle rinde mucho menos que invertir ese tiempo en una variante del ciclo de caminar — cojeando, arrastrando un pie — porque el clonaje se delata sobre todo cuando el grupo avanza en formación.
3.4 Turn-in-place por ángulo acumulado
Implementado (Lote 43). El proyecto usa la técnica de estándar AA. Está en el C++ y compilada; no hay que elegir nada. Esta sección describe qué hay que entregar para alimentarla.
Cómo funciona
La malla no acompaña al actor. Cuando el actor rota (porque la jugadora mueve la cámara apuntando, o porque la IA encara al objetivo), la malla se queda plantada donde estaba y acumula un desfase: RootYawOffset. Los pies no se mueven.
Al superar TriggerAngle (50° por defecto) se dispara el estado de giro. El clip lleva dentro una curva que va de 0 a 1, y esa curva es la que devuelve el desfase a cero. Como la curva la dibuja el animador, la rotación del cuerpo ocurre exactamente en los frames en que los pies se despegan del suelo. Ahí está la diferencia con la técnica por ritmo de giro: los pies solo se mueven cuando la animación dice que se mueven.
Al sistema no le importa quién rota al actor — sirve igual para la jugadora apuntando, para un enemigo con bOrientRotationToMovement o para una tarea de Behavior Tree que lo gire a mano.
Qué hay que entregar
| # | Clip | Nota |
|---|---|---|
| 1 | Giro 90° izquierda | Inicio y fin parados, no un ciclo continuo |
| 2 | Giro 90° derecha | — |
| 3 | Giro 180° | Opcional pero muy recomendable: sin él, un giro completo se ve como dos de 90 seguidos |
Cada clip DEBE llevar una curva float llamada TurnYawWeight (configurable en el Data Asset), que empieza en 0 en el primer frame y llega a 1 en el último.
Cómo dibujarla, que es la parte que decide si esto se ve bien o mal:
- La curva no es lineal. Debe permanecer plana (en 0) durante la anticipación, subir durante el pivote real, y aplanarse otra vez (en 1) durante el asentamiento final.
- Si el clip planta el pie a mitad y luego arrastra el otro, la curva tiene dos rampas con una meseta entre ellas. Copiar el ritmo real de los pies es literalmente el trabajo.
- Una curva lineal en un giro de dos pasos produce deslizamiento en el paso lento. Es el fallo típico de este sistema y se ve enseguida.
Red de seguridad
Si un clip no trae la curva (o no llega a 1), el sistema cierra el giro por tiempo a los MaxTurnDuration segundos y escribe en el log:
<Personaje>: el clip de giro no expone la curva 'TurnYawWeight' o no llega a 1.
Turn in place cerrado por tiempo; revisa la Animation Sequence.
Si aparece ese aviso, el asset está incompleto. El personaje no se queda torcido — pero el giro se ve mal.
Configuración por especie (Data Asset → TurnInPlace)
| Campo | Defecto | Qué hace |
|---|---|---|
bEnabled | false | Encender solo cuando existan los clips con curva |
TriggerAngle | 50° | Umbral de disparo. ~30 = giros más frecuentes y cortos |
MaxRootYawOffset | 120° | Tope de torsión del cuerpo |
TurnCurveName | TurnYawWeight | Nombre de la curva |
MaxTurnDuration | 1.5 s | Red de seguridad |
MoveResetSpeed | 8 | Velocidad de realineado al empezar a andar |
bDisableWhileAiming | true | Ver abajo |
La decisión de bDisableWhileAiming
Por defecto está en true, y es la opción segura: apuntando, el arma tiene que mirar a donde mira la mira, y un desfase de 50° la desalinearía del retículo.
Para ponerlo en false — que es como lo resuelven los shooters en tercera persona — hacen falta dos cosas: clips de giro de apuntado (girar sin bajar el arma) y bajar TriggerAngle a ~30, de forma que el cuerpo nunca quede muy desalineado y los giros sean pequeños y frecuentes. El resultado es el paso lateral corto característico de apuntar en Gears o The Last of Us. Es una entrega adicional de 2–3 clips; merece la pena porque apuntar es la acción central del juego.
3.5 Tiempos de transición
Los tiempos de blend son el 50% de la sensación de calidad. Valores de partida del proyecto:
| Transición | Duración | Modo | Por qué |
|---|---|---|---|
| Idle → Locomotion | 0.20 s | Ease In/Out | — |
| Locomotion → Idle | 0.25 s | Ease Out | Frenar cuesta más que arrancar |
| Dentro del Blend Space (walk↔run) | — | lo gestiona el eje | No poner transición |
| Idle → TurnInPlace | 0.15 s | Linear | — |
| Cualquiera → Death | 0.10 s | Ease In | — |
| Cualquiera → Wading | 0.30 s | Ease In/Out | El agua entra despacio |
| Aim in / out | 0.15 s | Ease In/Out | Doctrina RE: apuntar debe sentirse deliberado |
Regla: cualquier transición con Blend Logic = Inertialization es preferible a un blend cruzado clásico para locomoción. La inercialización preserva la velocidad de los huesos y elimina el «salto elástico» de las transiciones mal resueltas.
Parte 4 · Montages y slots
4.1 Los slots del proyecto
Hay que crear estos slots en el esqueleto CC5 (Anim Slot Manager), y cada montage debe entregarse ya asignado a su slot:
| Slot | Grupo | Contenido | Aditivo |
|---|---|---|---|
FullBody | DefaultGroup | Ataques, stagger, derribo, agarre, esquiva, muerte, takedown, enrage, transición de fase | No |
UpperBody | DefaultGroup | Disparo, recarga | No |
HitReactAdditive | Grupo propio | Las 4 reacciones direccionales | Sí |
Por qué HitReactAdditive necesita grupo propio. Los slots del mismo grupo se cancelan entre sí. Si la reacción aditiva comparte grupo con FullBody, cada golpe recibido durante un ataque corta el ataque — y el aplomo deja de significar nada, porque el enemigo se vuelve interrumpible al 100%. El framework ya se protege por su lado (CanPlayMediumHitReaction niega la aditiva mientras el enemigo ataca o agarra), pero el slot debe estar bien de todas formas.
Crítico. El C++ usa PlayAnimMontage(Montage), que reproduce el montage en el slot con el que fue autorado. No hay forma de corregir un slot equivocado desde código sin tocar el asset. Un montage entregado en DefaultSlot cuando debía ir en UpperBody reproducirá el disparo con todo el cuerpo y parecerá un bug de gameplay. El slot es responsabilidad de la entrega.
4.2 Tiempos de blend de los montages
| Familia | Blend In | Blend Out | Nota |
|---|---|---|---|
| Ataques | 0.05 – 0.08 s | 0.20 s | Ver aviso abajo |
| Stagger | 0.05 s | 0.20 s | Debe leerse como impacto, no como transición |
| Derribo | 0.10 s | 0.30 s | — |
| Agarre | 0.15 s | 0.25 s | — |
| Esquiva | 0.05 s | 0.15 s | — |
| Muerte | 0.10 s | — | — |
| Reacciones aditivas | 0.08 s | 0.25 s | El blend out largo evita el corte seco |
| Recarga / disparo | 0.10 s | 0.15 s | — |
El aviso de los ataques. Un blend in largo hace que la ventana de daño se abra mientras la pose todavía se está mezclando. El jugador ve el golpe llegar tarde respecto al daño que recibe, y la sensación es de hitbox injusta aunque el código sea correcto. Por eso los ataques entran casi a corte: 0.05–0.08 s, nunca más de 0.10.
4.3 Anticipación y legibilidad
En survival horror la legibilidad del ataque es el diseño de combate.
- Wind-up mínimo 0.35 s para melee de enemigo básico. Por debajo de 0.30 s el jugador no tiene ventana de reacción y el combate se percibe como aleatorio.
- El wind-up debe ser legible en silueta: el brazo sale del contorno del cuerpo. Si hay que ver la mano para saber que viene el golpe, no funciona a media distancia ni con poca luz — y este juego es oscuro por diseño.
- Recovery mínimo 0.5 s tras el impacto. Es la ventana de castigo. Sin recovery el combate no tiene ritmo de intercambio, solo de esquiva.
- Ataques distintos del mismo enemigo deben tener wind-ups visualmente distintos. Si el zarpazo y el mordisco empiezan igual, el jugador no puede elegir respuesta y da igual que sean dos ataques.
Parte 5 · Notifies: lo que cada montage debe llevar dentro
5.1 SHAnimNotifyState_DamageWindow — obligatorio en TODO montage de ataque
Es un Notify State (tiene duración, no es un evento puntual). Abre la ventana en NotifyBegin, la evalúa cada frame en NotifyTick y la cierra en NotifyEnd.
- Empieza en el frame donde el arma/miembro entra en la zona de peligro visual; termina donde sale.
- Duración típica: 0.10 – 0.20 s (6–12 frames a 60 fps). Más de 0.25 s hace el ataque imposible de esquivar y se percibe como injusto.
- Un solo DamageWindow por ataque, salvo que el ataque sea explícitamente de dos golpes — en cuyo caso son dos ventanas separadas, no una larga.
Un montage de ataque sin este notify no hace daño. Es el fallo silencioso más común: la animación se ve, el enemigo ataca, y no pasa nada.
5.2 SHAnimNotify_Footstep — en todo ciclo de locomoción
Notify puntual. Traza al suelo desde FootSocketName, detecta el material físico y dispara FX de Niagara + sonido por superficie.
- Uno en cada contacto de talón, en el frame exacto del contacto (no uno antes, no uno después: el desfase entre el sonido y el pie se oye).
- Configurar
FootSocketNameafoot_l/foot_rsegún corresponda. - También en los ciclos de caminar hacia atrás, de strafe y de giro. Olvidarlos ahí es el segundo fallo más común, y produce enemigos que se acercan en silencio por el lateral.
- En el clip de reptar del rastrero: en el contacto de mano y de rodilla, no de pie.
5.3 Notify de Motion Warping
Previsto en el diseño de FSHAttackDef. Va en la ventana donde el ataque avanza hacia el objetivo, antes del DamageWindow. Delimita el tramo en el que el motor puede corregir la posición para que el golpe llegue.
5.4 Notifies de sonido y VFX
Cualquier sonido que no sea pisada (rugido, roce de ropa, chasquido de hueso) va como notify propio en el montage, no en el Event Graph del ABP. Recordatorio: el Event Graph queda vacío.
Parte 6 · Lista de entregables por arquetipo
Esto es la orden de trabajo. Cada línea se corresponde con un campo real del Data Asset (DA_ED_*), así que cuando esté entregado, montarlo es arrastrar el asset a su casilla.
6.1 Paquete base — todo enemigo bípedo
| Asset | Campo del Data Asset | Root motion | Slot |
|---|---|---|---|
| Idle A (≥4 s) | — (va al ABP) | No | — |
| Idle B (silueta distinta) | IdleVariantCount = 2 | No | — |
| Locomoción: 4 dir × 2 velocidades | — (Blend Space) | No | — |
| Giro 90 izq / 90 der / 180 | TurnInPlace + curva | No | — |
1 montage por entrada de Attacks[] | Attacks[i].Montage | No + Warp | FullBody |
| Stagger | StaggerMontage | No | FullBody |
| Derribo (caída + levantada, un clip) | KnockdownMontage | Sí | FullBody |
| Reacción frontal | HitReactFrontMontage | No | HitReactAdditive |
| Reacción trasera | HitReactBackMontage | No | HitReactAdditive |
| Reacción izquierda | HitReactLeftMontage | No | HitReactAdditive |
| Reacción derecha | HitReactRightMontage | No | HitReactAdditive |
| Víctima de takedown | TakedownVictimMontage | Sí | FullBody |
Mínimo viable de un enemigo básico: ~23 clips, con dos ataques y sin extras.
6.2 Paquetes opcionales — solo si la especie los tiene
| Sistema | Asset | Campo |
|---|---|---|
Agarre (bCanGrab) | Montage de agarre | GrabMontage |
| Defensa activa | Montage de esquiva | DodgeMontage |
| Enfurecimiento | Montage de enrage (rugido) | EnrageMontage |
| Fases (jefes) | 1 montage por fase | Phases[i].TransitionMontage |
6.3 Paquete del rastrero (mutación por amputación)
BP_PenitentCrawler es la especie que emerge cuando al penitente le cercenan una pierna en vida (MutateOnSeverAliveClass). Comparte esqueleto CC5, así que su ABP puede ser un Child Animation Blueprint del penitente: hereda el grafo cableado y solo sustituye los clips.
| # | Asset | Nota |
|---|---|---|
| 1 | Idle de rastrero | Tumbado, respiración pesada |
| 2–4 | Reptar: adelante, giro izq, giro der | Notify de pisada en mano y rodilla |
| 5 | Ataque desde el suelo (agarre de tobillo) | El ataque canónico del rastrero |
| 6 | Transición: caída al perder la pierna | Se reproduce en el momento de la mutación |
| 7–10 | Las 4 reacciones aditivas, versión tumbada | Las de pie no funcionan tumbado |
Nota de diseño. El paso 6 es el que vende la mutación entera. Si el rastrero simplemente aparece, se lee como un bug de spawn; si se ve caer, se lee como consecuencia.
6.4 Paquete de la jugadora
Mismo esquema del 6.1, más:
- Locomoción 8 direcciones (es la cámara la que la mira todo el rato)
- Ciclo agachado (4 direcciones mínimo)
- Salto: despegue, aire, aterrizaje
- Vadeo (
bIsWading) AO_Player_Aim— Aim Offset de 5 poses (o 9–15 si se usa turn-in-place al apuntar)- Por arma: pose aditiva de overlay + montage de disparo + montage de recarga (slot
UpperBody) - Giro rápido (
QuickTurnMontage, ya referenciado enSHPlayerCharacter) - Montage de takedown, sincronizado frame a frame con
TakedownVictimMontagedel enemigo - Escalera (
State.Climbing)
Parte 7 · Checklist de aceptación
Ningún asset entra al proyecto sin pasar esto. Cada punto se verifica en el editor, no de palabra.
Por clip
- Esqueleto = CC5, sin huesos extra ni renombrados
- Root en el origen con rotación identidad en frame 0 (clips in-place)
- Sin deriva del root en clips in-place
- Contacto de suelo en Z = 0
- Bucle sin frame duplicado al final
- Sin deslizamiento de pies a la velocidad de gameplay real
- Nomenclatura correcta
Por Blend Space
- Nombres y rangos de eje según 2.2
- Clip de «hacia atrás» colocado en +180 y en −180
- Cada muestra en la coordenada de su velocidad de captura
- Fila Speed = 0 vacía
- Interpolation Times: 0.15 (Direction) / 0.10 (Speed)
- Sync Markers en cada pisada de TODOS los clips, mismos nombres y mismo número (ver A.4)
- Mismo número de fotogramas dentro de cada fila
Por clip de giro
- Curva
TurnYawWeightpresente, de 0 a 1 - La curva sigue el ritmo real de los pies (no lineal)
- Inicio y fin parados
- Notifies de pisada incluidos
Por Montage
- Slot correcto (
FullBody/UpperBody/HitReactAdditive) - Las reacciones son aditivas y están en su grupo propio
- Blend In/Out según la tabla 4.2
- Ataques:
DamageWindowpresente, 0.10–0.20 s, en los frames del barrido real - Ataques: wind-up ≥ 0.35 s y legible en silueta
- Locomoción:
Footstepen cada contacto de talón, también en back, strafe y giro
Por ABP
- Hereda de
SHAnimInstance - Event Graph vacío
- Orden de capas del 3.1 respetado (Rotate Root Bone arriba, IK la última)
AnimPhaseOffset→ Start Position del idleAnimPlayRateScale→ Play Rate de idle y locomoción, y de nada másbMirrorPose→ nodo Mirror, con su Mirror Data Table asignadaRootYawOffset→ pin Yaw del Rotate Root Bone- Ningún cast al personaje, ninguna llamada a componentes
En playtest
- Tres del mismo enemigo juntos no respiran sincronizados
- Al girar parado, los pies no patinan
- No aparece el aviso de curva de giro ausente en el log
- El ataque se lee a 10 metros con la iluminación del nivel, no con la del viewport
- El stagger se distingue de la reacción aditiva a simple vista
- Los pies no patinan cuando el enemigo persigue por NavMesh
- El sonido de pisada coincide con el frame del pie
Parte 8 · Los siete errores que matan el acabado AA
Ordenados por frecuencia real, no por gravedad teórica.
- Mentir en el eje Speed del Blend Space. Colocar el ciclo de caminar donde queda cómodo en vez de a su velocidad de captura. Produce deslizamiento permanente, y como nunca se corrige en el clip sino «compensando» en otro sitio, contamina todo el sistema.
- Blend times por defecto. Dejar los 0.25 s que UE pone en todo. La locomoción queda blandengue y los impactos pierden el golpe seco.
- El frame duplicado del bucle. Un tirón por vuelta, invisible en el viewport de la Animation Sequence y evidente en el juego.
- Root motion donde no toca. Un ciclo de locomoción con root motion pelea con el NavMesh y produce enemigos que se atascan en las esquinas. El síntoma se diagnostica como «bug de IA» y se pierden días buscando en el Behavior Tree.
- La reacción aditiva en el slot equivocado. Comparte grupo con
FullBody, cancela los ataques, y el enemigo se vuelve interrumpible al 100%. El aplomo — un sistema entero — deja de existir sin que nadie toque su código. - Wind-ups indistinguibles. Dos ataques que empiezan igual son un solo ataque con dos finales. El jugador no puede elegir respuesta y el combate se percibe como aleatorio.
- Lógica en el Event Graph del ABP. Funciona en el prototipo, y revienta el día que hay que cambiar cómo se dispara una reacción — porque la verdad pasa a estar en dos sitios. El contrato de la Parte 0 existe precisamente para que esto no ocurra.
Anexo A · Las muestras del Blend Space, una por una
Este anexo desarrolla la sección 2.3 para quien no viene de animación. Describe qué contiene cada clip y por qué está donde está, en los dos niveles de acabado.
A.0 Qué significa «muestra», y el concepto que lo desbloquea todo
Un Blend Space es una cuadrícula. Se colocan animaciones en puntos concretos; en runtime el motor calcula una posición dentro de la cuadrícula y mezcla automáticamente las animaciones más cercanas. No se anima el caso intermedio: se animan las esquinas y el motor rellena.
Una muestra es una animación clavada en una coordenada de esa cuadrícula.
El concepto clave: el personaje siempre mira al frente.
Directiones hacia dónde se desplaza, no hacia dónde mira.Direction = 90significa el pecho apunta al frente pero el cuerpo se desliza a la derecha — un paso lateral, no un giro. El personaje nunca gira dentro de este Blend Space.
Por eso el set se llama «de strafe»: permite que la jugadora camine hacia atrás sin dejar de apuntar, o que un enemigo la rodee sin perderla de vista. Convenio de signos de Unreal: positivo = derecha, negativo = izquierda.
0 grados (frente)
^
-45 \ | / +45
\ | /
-90 <------------- [ACTOR] -------------> +90
(izquierda) | (derecha)
-135 / | \ +135
v
+-180 / -180 (atras)
−180 y +180 son el mismo punto físico: justo detrás. Es un círculo cortado y estirado en línea recta; los dos extremos del corte eran el mismo sitio. De ahí la aritmética que confunde al principio.
| Nivel | Clips que anima el animador | Muestras colocadas |
|---|---|---|
| Sólido | 8 | 10 (el clip de «atrás» se coloca dos veces, en cada fila) |
| AA | 16 | 18 (mismo motivo) |
Sobre las dos filas: se dicen «andar» y «correr» por comodidad, pero son velocidad lenta y velocidad rápida, y qué significan lo decide el Data Asset de cada criatura. Para la jugadora: 200 / 450. Para el Penitente, un carroñero que arrastra los pies, será más bien arrastrarse 60 / caminar amenazante 150 — y probablemente no tenga fila rápida en absoluto. La estructura es idéntica; cambian los números y el carácter.
A.1 Nivel sólido — 8 clips, 10 muestras
-180 -90 0 +90 +180
atras izq frente der atras
RAPIDO (450) -- 10 --- 08 --- 06 --- 07 --- 09
| | | | |
LENTO (200) -- 05 --- 03 --- 01 --- 02 --- 04
| | | | |
0 (fila VACIA: el idle vive en su propio estado)
Fila lenta
01 · Andar de frente — Direction 0, Speed 200
El clip base, la referencia de todo lo demás. Talón que golpea primero, el pie rueda hasta la punta, empuje. Brazos opuestos a las piernas. Hombros y caderas contrarrotan ligeramente — eso es lo que hace que un caminar parezca vivo y no un maniquí deslizándose.
Crítico. Zancada × cadencia debe dar exactamente 200 cm/s. Este número se mide, no se estima. Si el actor camina a su ritmo natural pero el juego lo mueve a 200, los pies patinan.
02 · Paso lateral derecho — Direction +90, Speed 200
El pecho sigue apuntando al frente; el cuerpo se desplaza a la derecha. La pierna izquierda cruza por delante de la derecha, la derecha sale a buscar espacio. Las caderas se adelantan un poco hacia la marcha; los hombros se quedan cuadrados al frente.
El error número uno. El instinto del actor de mocap es girarse hacia donde camina. Hay que decírselo explícitamente antes de rodar: «el pecho no se mueve de esa marca, tú te desplazas de lado». Un clip con el actor girado 20° está inservible y no se arregla en post.
03 · Paso lateral izquierdo — Direction −90, Speed 200
El espejo del anterior: ahora cruza la derecha por delante de la izquierda.
Se captura, no se espeja en el software. Los humanos somos asimétricos (pierna dominante) y un lateral espejado se lee como robótico. Para la jugadora, capturarlo. Para un enemigo secundario, espejarlo es un atajo aceptable.
04 · Retroceder — Direction +180, Speed 200
Contacta primero la punta del pie, nunca el talón — ese detalle es el que vende el clip entero. Zancada más corta que hacia delante, torso ligeramente inclinado hacia adelante para contrapesar, brazos algo separados del cuerpo buscando equilibrio.
El error clásico. Entregar el clip de andar de frente reproducido al revés. Se nota inmediatamente porque el talón toca primero y el peso va invertido. Un retroceso real es más cauteloso y más corto.
05 · Retroceder (repetido) — Direction −180, Speed 200
Es el mismo archivo que 04. No se anima nada nuevo: se arrastra el mismo asset a la coordenada del otro extremo. Es la costura del círculo.
Fila rápida
06 · Correr de frente — Direction 0, Speed 450
Zancada larga y fase de vuelo: hay fotogramas sin ningún pie en el suelo. Es lo que separa correr de andar rápido. Torso inclinado 5–15° hacia delante, brazos bombeando con el codo a ~90°.
Error típico. Un ciclo demasiado corto. A 450 cm/s la zancada es larga; con los mismos fotogramas que el de andar parece una caricatura acelerada.
07 · Desplazamiento lateral rápido derecha — Direction +90, Speed 450
Verdad física: nadie «corre de lado». Lo que hace un humano es un bote lateral: empuja con el pie de atrás, aterriza sobre el de delante, con un pequeño momento aéreo. Base ancha, centro de gravedad bajo, torso al frente pero inclinado hacia la marcha.
Aquí NO se cruzan las piernas. A velocidad de paso sí; a velocidad de carrera es inestable y se lee mal.
08 · Desplazamiento lateral rápido izquierda — Direction −90, Speed 450
Espejo del anterior, mismas notas.
09 · Retroceder rápido (backpedal) — Direction +180, Speed 450
Rodillas altas, apoyo sobre la parte delantera del pie, torso erguido o muy ligeramente inclinado adelante, brazos abiertos para equilibrar.
Aviso honesto, decisión de diseño. Un humano no retrocede tan rápido como corre de frente: el máximo real ronda el 60–70% de la velocidad de carrera. Si el gameplay mueve al personaje hacia atrás a 450, ese clip patinará por bien capturado que esté. Dos salidas: bajar la velocidad de retroceso (es un dato del Data Asset, no código) o aceptar una exageración deliberada. Para zombis lentos da igual; en la jugadora se nota.
10 · Retroceder rápido (repetido) — Direction −180, Speed 450
El mismo archivo que 09, en el otro extremo.
A.2 Nivel AA — 16 clips, 18 muestras
Los 8 anteriores más las cuatro diagonales en cada fila. Para la jugadora y para enemigos con rol de Flanqueador o Acosador, que sí orbitan.
-180 -135 -90 -45 0 +45 +90 +135 +180
RAPIDO -- 18 -- 16 -- 14 -- 12 -- 10 -- 11 -- 13 -- 15 -- 17
| | | | | | | | |
LENTO -- 09 -- 07 -- 05 -- 03 -- 01 -- 02 -- 04 -- 06 -- 08
Por qué existen las diagonales
Es la pregunta correcta: si el motor ya mezcla, ¿por qué animar el 45° pudiendo mezclar frente con lateral?
Porque una mezcla no es una animación. Al promediar el clip de frente con el de lateral, el motor promedia también las posiciones de los pies — y salen pies que aterrizan donde ningún pie aterrizaría, deslizándose para llegar. Es el efecto «nadar» que delata un sistema de locomoción barato.
Un 45° capturado de verdad tiene su propio patrón de pisadas, correcto, y el motor solo mezcla entre vecinos muy parecidos. Esa es literalmente toda la diferencia entre el nivel sólido y el nivel AA.
Las diagonales, fila lenta
02 · Diagonal adelante-derecha — Direction +45, Speed 200
Avanza y se abre a la derecha a la vez, con el pecho todavía al frente. Los pies se abren en abanico hacia el lado derecho: el derecho pisa más afuera, el izquierdo cruza ligeramente hacia el centro. Las caderas se abren un poco; los hombros no.
03 · Diagonal adelante-izquierda — Direction −45, Speed 200
Espejo del anterior.
06 · Diagonal atrás-derecha — Direction +135, Speed 200
Retrocede abriéndose a la derecha. Punta del pie primero (como todo lo que va hacia atrás), zancada corta, cadera derecha abierta.
Es el movimiento de «me retiro sin dejar de mirarte» — el más usado por la jugadora cuando un enemigo se le echa encima. Merece cuidado extra.
07 · Diagonal atrás-izquierda — Direction −135, Speed 200
Espejo del anterior.
Las diagonales, fila rápida
11 / 12 — Direction ±45, Speed 450
Carrera abriéndose en diagonal. Más natural que el lateral puro: el cuerpo puede inclinarse hacia la curva como quien toma un viraje corriendo.
15 / 16 — Direction ±135, Speed 450
Retroceso rápido en diagonal. El más difícil de capturar bien y el que más se nota cuando está mal, porque combina las dos cosas antinaturales: ir hacia atrás y de lado a la vez.
08 / 17 son las repeticiones de «atrás» en −180, igual que en el nivel sólido.
A.3 Reglas que aplican a las 10 o a las 18, sin excepción
- Todas en el sitio (in-place). El personaje pedalea sin desplazarse; lo mueve el motor.
- Todas en bucle, sin duplicar el primer fotograma al final.
- Contacto del talón derecho en el frame 0 en todas.
- Mismo número de fotogramas dentro de cada fila.
- Notify de pisada en cada contacto, también en laterales, diagonales y retrocesos.
- Cada clip en la coordenada de su velocidad de captura. Si el lateral salió a 180 cm/s y no a 200, o se recaptura o se cambia el dato — no se coloca en la casilla de 200 y a correr.
A.4 Marcadores de sincronía (Sync Markers) — requisito de entrega
El detalle que más calidad da y que casi nadie menciona.
Cuando el motor mezcla el clip de frente con el de lateral, por defecto los reproduce por tiempo: si uno va por el 30% y el otro por el 70%, mezcla un pie en el aire con un pie en el suelo. El resultado es un temblor sutil en los pies que nadie sabe explicar.
Los Sync Markers son etiquetas que se colocan en cada pisada de todos los clips (convención del proyecto: L en el contacto del pie izquierdo, R en el derecho). Con ellos el motor deja de sincronizar por tiempo y sincroniza por pisada: alinea el pie izquierdo de un clip con el pie izquierdo del otro.
- Todos los clips de un mismo Blend Space usan los mismos nombres de marcador.
- Todos deben tener el mismo número de marcadores y en el mismo orden.
- Es trabajo de minutos por clip y es la diferencia más grande entre «se ve bien» y «se ve como Manny y Quinn».
Sin Sync Markers, un Blend Space de 18 muestras perfectas rinde peor que uno de 10 con ellos.
Apéndice · Orden de trabajo sugerido
Para que haya algo jugable lo antes posible y el resto se acumule encima:
- Bloque 1 — el suelo: locomoción 4 direcciones × 2 velocidades + 2 idles + los 3 clips de giro con su curva. Valida el Blend Space, el anti-clones, el turn-in-place y los notifies de pisada.
- Bloque 2 — el combate mínimo: 2 ataques + stagger + las 4 reacciones aditivas. Valida todo el pipeline de daño de punta a punta.
- Bloque 3 — la carne: derribo, agarre, muerte, takedown.
- Bloque 4 — el rastrero: el paquete 6.3 completo, con la caída de la mutación.
- Bloque 5 — la jugadora: paquete 6.4, el más grande y el que más iteración pide.
Validar cada bloque en el juego antes de empezar el siguiente. Una corrección de criterio en el bloque 1 cuesta un día; la misma corrección descubierta en el bloque 5 cuesta la recaptura de todo lo anterior.