Todos los artículos
8 min de lectura

Hit Reactions tipo Euphoria para Godot: código abierto en seis días

Las reacciones físicas de personajes de Euphoria llevan 18 años encerradas tras tecnología propietaria. Pasé seis días construyendo Kickback, un plugin de código abierto para Godot que lleva los mismos principios a los desarrolladores indie.

Godot Physics Open Source Game Dev

Todos los desarrolladores de juegos han visto ese momento en GTA IV. Le disparas a un NPC en una escalera y no reproduce una animación de muerte enlatada — tropieza, se agarra a la barandilla, pierde el agarre y cae rodando de una forma que nunca es exactamente igual. Eso es el motor Euphoria de NaturalMotion. Es propietario, lleva sin estar disponible para nadie fuera de un puñado de estudios AAA desde 2006, y no existe alternativa de código abierto.

Pasé seis días construyendo una para Godot. El resultado es Kickback — un plugin con licencia MIT que lleva reacciones físicas a impactos a cualquier personaje humanoide.

Kickback euphoria showcase — stagger, resistencia activa, escalado de dolor, lesiones

Qué hace realmente Euphoria

La mayoría de juegos manejan los impactos de dos formas: reproducir una animación enlatada (“hit_front”), o activar ragdoll completo al morir. Ninguna produce las reacciones emergentes que ves en GTA o Red Dead Redemption.

La clave de Euphoria es que los personajes son agentes activos intentando sobrevivir. No solo caen — se apoyan contra paredes, mueven los brazos para equilibrarse, dan pasos correctivos para evitar caer. Cada hueso del cuerpo está simulado por físicas, pero una capa de inteligencia lucha por mantener al personaje en pie.

El resultado es que cada impacto es único. Un personaje corriendo cae hacia adelante. Uno de pie se tambalea lateralmente. Disparos repetidos desgastan visiblemente al objetivo. La misma arma, el mismo blanco, el mismo ángulo — resultado diferente cada vez.

Ese es el listón. Kickback no lo alcanza del todo, pero implementa muchos de los mismos principios subyacentes.

El enfoque basado en springs

Kickback crea un rig de físicas invisible con 16 cuerpos RigidBody3D conectados por 15 joints, reflejando el esqueleto de animación del personaje. Cada frame de físicas, springs basados en velocidad tiran de cada cuerpo físico hacia la pose de animación. Cuando los springs están a máxima fuerza, el personaje sigue perfectamente su animación. Cuando un impacto reduce la fuerza de los springs, las físicas ganan y el cuerpo reacciona.

El núcleo es sorprendentemente compacto:

# For each of the 16 bones, every physics frame:
var target_rotation = get_animation_bone_pose(bone_index)
var current_rotation = physics_body.global_transform.basis
var rotation_error = (target_rotation * current_rotation.inverse()).get_euler()
var target_angular_velocity = rotation_error / delta
var blend = strength  # 1.0 = animation, 0.0 = ragdoll
physics_body.angular_velocity = physics_body.angular_velocity.lerp(target_angular_velocity, blend)

Cuando una bala impacta, strength baja de 1.0 hacia cero en la región afectada. El cuerpo del personaje reacciona a la fuerza del impacto mientras los springs en áreas no afectadas mantienen el resto del cuerpo siguiendo la animación. Con el tiempo, la fuerza se recupera y la animación retoma el control.

Cinco perfiles de impacto vienen con el plugin — bala, escopeta, explosión, melee, flecha — cada uno produciendo una reacción distinta:

Cinco perfiles de arma produciendo reacciones distintas — bala, melee, flecha, escopeta, explosión

¿Por qué no PhysicalBone3D?

Godot tiene un nodo PhysicalBone3D integrado. Parece la opción obvia para un sistema de ragdoll. El problema: le faltan métodos críticos.

FuncionalidadPhysicalBone3DRig dual de RigidBody3D
apply_force()No
apply_torque()No
Señales de colisiónNo
center_of_massNo
contact_monitorNo

Sin apply_force(), no puedes construir un sistema de springs que aplique fuerzas correctivas continuas. Sin señales de colisión, no puedes detectar impactos. Sin center_of_mass, no puedes rastrear el equilibrio.

Así que Kickback construye su propio rig: 16 cuerpos RigidBody3D con masas distribuidas anatómicamente (caderas a 15kg, cabeza a 5kg, manos a 1kg cada una), conectados por joints Generic6DOFJoint3D con límites angulares anatómicos. Cada frame de físicas, los transforms de estos cuerpos invisibles se escriben de vuelta al esqueleto visible como bone pose overrides.

Más infraestructura, pero desbloquea todo lo que el sistema necesita.

Las partes contraintuitivas

Tres cosas me sorprendieron durante el desarrollo:

La animación nunca se detiene. Incluso cuando un personaje está completamente ragdolleado en el suelo, su animación sigue reproduciéndose. Parece incorrecto — ¿para qué animar un cuerpo inerte? Pero el spring resolver necesita poses objetivo. Sin la animación proporcionando “aquí es donde está lo normal”, los springs no tienen hacia dónde tirar y la recuperación se vuelve imposible.

Los timers se ven falsos. El stagger inicial usaba un timer fijo: tambaleo durante N segundos, luego recuperación. El problema era visible — un personaje que ya había recuperado el equilibrio seguía tambaleándose, y uno claramente cayéndose se enderezaba de golpe cuando expiraba el timer. La solución fue rastreo de equilibrio basado en físicas. El sistema calcula el centro de masa (promedio ponderado por masa de las 16 posiciones de los cuerpos) y lo compara con el polígono de soporte entre los pies. ¿Recuperas el equilibrio antes? El stagger termina antes. ¿Pierdes el equilibrio sin importar el timer? Ragdoll.

El tambaleo no debe repetirse nunca. El balanceo del stagger usa ratios de frecuencia irracionales (1.73x, 2.17x) para que el patrón de oscilación matemáticamente nunca se repita. La deriva perpendicular crea movimiento en forma de 8. Cada stagger recibe un desfase de fase aleatorio. El resultado parece orgánico y animado a mano — pero es completamente procedural.

Integración en juego — los NPCs caminan, reciben impactos, se tambalean, se recuperan y siguen adelante

Seis días, 94 commits

DíaEnfoqueHito
1-2FundamentosEsqueleto dual, springs basados en velocidad, 5 perfiles de arma, recuperación
3Arquitectura + staggerConfiguración basada en Resources, auto-detección de esqueleto, estado de stagger, transferencia de momento, dolor acumulativo, lesiones regionales
4Resistencia activaAjuste dinámico de springs por hueso, balanceo orgánico, 59 tests automatizados
5Tests de integraciónProbado con un FPS real, corregidos 8 problemas de integración
6Lanzamiento públicov0.7.0 en GitHub, GIFs de demo, documentación

Recuento final: 59 tests con 161 aserciones, 10 escenas de demo interactivas, más de 1.600 líneas de documentación, y más de 35 parámetros ajustables — todos expuestos como Resources de Godot sin ningún valor hardcodeado.

Huesos protegidos vs no protegidos — mismo impacto, resultado radicalmente diferente

Lo que falta

Kickback implementa los músculos. Lo que falta es el cerebro.

Los personajes de Euphoria dan pasos correctivos cuando pierden el equilibrio. Mueven los brazos como aspas. Se agarran a paredes y barandillas cercanas. Generan poses completamente emergentes sin necesidad de animaciones objetivo. Los personajes de Kickback no hacen nada de eso — son sistemas de springs pasivos que las físicas empujan y los springs tiran de vuelta.

La hoja de ruta incluye pasos procedurales de tropiezo, apoyo con brazos y agarre al entorno. Pero son problemas difíciles — cada uno es un proyecto significativo por sí solo. Por ahora, el sistema de springs cubre el espectro desde estremecimientos sutiles hasta ragdoll completo, y el estado de stagger llena el hueco crítico entre “de pie” y “en el suelo”.

Lo que aprendí

Pelea contra el motor cuando la API no sirve. PhysicalBone3D existe, y construir un rig paralelo parecía un desperdicio. Pero los métodos que faltaban eran innegociables. A veces la herramienta integrada no es la herramienta correcta.

Los springs basados en velocidad superan a los parámetros de joints. Los springs integrados de Jolt están mal documentados, tienen problemas de espacios de coordenadas y ejes invertidos. El lerp manual de velocidad es más simple, depurable y escala uniformemente. La comunidad de V-Sekai y el creador de Jolt Physics recomiendan este enfoque.

Las físicas necesitan animación activa. La decisión contraintuitiva que lo desbloqueó todo. Ragdoll sin poses objetivo de animación es solo un esqueleto colapsándose.

El centro de masa supera a los timers. Las transiciones de estado basadas en timers se sienten arbitrarias. El rastreo de equilibrio basado en físicas responde a lo que realmente le está pasando al personaje, y los jugadores lo leen intuitivamente.

La documentación es el último 20% que lleva el 30% del tiempo. 1.600 líneas de documentación, 10 escenas de demo, 5 GIFs capturados — esto es lo que hace un plugin usable frente a simplemente funcional. Nadie va a adoptar un sistema de físicas que no puede ver funcionando.

Pruébalo

Kickback está en GitHub. Licencia MIT. Godot 4.6+ con Jolt Physics. Dos clics para añadirlo a cualquier personaje humanoide, una línea de código para enviar impactos.

Se aceptan pull requests — especialmente si tienes esqueletos que no sean Mixamo para probar.

Debug gizmos — puntos de hueso, wireframe, dashboard completo con centro de masa y vectores de velocidad

Ignacio María Muñoz Márquez

Ignacio María Muñoz Márquez

Senior Game Programmer

Articulos relacionados