Skip to content

blugart-dev/kickback

Repository files navigation

Kickback

Tests Godot 4.7+ License: MIT

Physics-based reactive characters for Godot 4.7+

Inspired by NaturalMotion's Euphoria engine (GTA IV/V, Red Dead Redemption). Characters react dynamically to gunshots, explosions, melee hits, and arrows using active ragdoll physics — every hit produces a unique, physically-driven reaction.

See It In Action

Run any scene from demo/ in the Godot editor to see the plugin live:

  • euphoria_showcase.tscn — Best overview: active resistance, stagger sway, pain escalation, injuries
  • shooting_range.tscn — FPS shooting with 5 weapon profiles + ball-throw alt-fire
  • tuning_playground.tscn — Tuning Lab: 5 presets side-by-side + a Custom character with 35+ live sliders

Press F3 in any demo to cycle debug gizmos (bone dots → wireframe → full dashboard).

Kickback euphoria showcase — stagger, active resistance, pain escalation, injuries

Weapon variety — 5 impact profiles, each producing a distinct reaction

Shooting range with bullet, melee, arrow, shotgun, and explosion impacts

Game integration — NPCs walk, get hit, recover, and keep going

NPCs patrol, react to hits, recover with injuries, and resume

Project status

Kickback is pre-1.0 and actively evolving. It has a robust passive reaction foundation — velocity springs, balance sensing, a full state machine, terrain foot IK — but the active self-preservation behaviors that define Euphoria (stumble-stepping, arm/wall bracing, grabbing, procedural poses) are still ahead.

By difficulty-weighted progress toward that goal, the project is at ~30% — which is exactly what the version 0.3.x is meant to convey. 1.0.0 is reserved for full Euphoria parity. See ROADMAP.md for the scorecard and milestones, and VERSIONING.md for what the numbers mean.

Today it works well as a hit-reaction system for humanoid (Mixamo-style) rigs. General multi-rig robustness and the self-preservation layer are on the roadmap.

Features

  • Active ragdoll — 16 RigidBody3D physics skeleton tracks animation via velocity-based springs. Hits reduce spring strength so physics temporarily wins. Full ragdoll with automatic get-up recovery.

  • Stagger state — between absorption and full ragdoll. Character visibly wobbles but stays on feet. Configurable threshold, duration, and escalation on follow-up hits.

  • Balance tracking — center of mass vs foot support polygon drives stagger behavior. Characters that lean too far ragdoll; balanced characters recover early. Physics-informed, not timer-based.

  • Momentum transfer — running characters carry their velocity into ragdoll, tumbling forward instead of dropping in place.

  • Fatigue — repeated hits degrade effective spring strength over time. Fatigued characters wobble more at baseline and recover to lower maxes. Decays slowly between engagements.

  • Hit stacking — rapid consecutive hits escalate via streak multiplier. Hits during recovery can interrupt get-up and re-ragdoll the character.

  • Reaction pulses — sub-stagger hits produce a brief visible wobble that fades over 200ms. Even light hits are noticeable.

  • Directional bracing — during stagger, bones opposite the hit direction strengthen while hit-side bones weaken further. Characters visibly fight to stay upright.

  • Active Resistance — during stagger, per-bone spring strengths dynamically adjust every physics frame. Counter-side bones stiffen against imbalance, core engages progressively, load-bearing leg braces. Degrades with fatigue. Characters actively fight to stay upright instead of passively wobbling.

  • Stagger sway force — continuous oscillating force on core bones during stagger creates visible back-and-forth wobble as springs fight the force. Decays quadratically over stagger duration.

  • Cumulative pain — sustained fire deterministically escalates reactions (flinch → stagger → ragdoll) instead of relying on dice rolls. Pain decays between engagements.

  • Movement-aware hits — running characters are less stable and stagger more easily. Stagger direction blends with movement direction for natural stumbling.

  • Threat anticipationanticipate_threat(direction, urgency) API for pre-hit flinch. Call when bullets fly nearby or an enemy winds up an attack.

  • Micro hit reactions — torso bend, head whip, and spin torque at the moment of impact. Every hit has a visceral split-second reaction.

  • Regional impairment — persistent per-bone injury that outlasts spring recovery. Shot in the leg causes visible sag/limp. Shot in the arm makes it dangle. Injuries heal slowly.

  • Protected bones — mark bones (e.g., legs) that never weaken from hits. Upper body reacts to impacts while legs stay animated and feet stay planted.

    Protected vs unprotected bones — same hit, different result
  • Always-simulated rig — physics bodies never freeze, springs are always active. Hit reactions feel immediate with no startup delay.

  • Skeleton auto-detectionSkeletonDetector identifies humanoid bones in Mixamo, Rigify, Unreal Mannequin, and custom skeletons.

  • Animation-agnostic — works with AnimationPlayer, AnimationTree, or any system that drives Skeleton3D bone poses. Controllers emit signals; animation is the user's responsibility.

  • Configurable everything — skeleton mapping (RagdollProfile), physics tuning (RagdollTuning), impact parameters (ImpactProfile) — all via Resources with sensible defaults.

  • Hit detection utilityKickbackRaycast.shoot_from_camera() handles raycast + routing in one line.

  • Debug gizmos — F3 cycles through 3 detail levels: bone dots → skeleton wireframe + state labels → full dashboard with status panels, center of mass, velocity vectors, and balance/fatigue bars.

  • 8 demo scenes — comparison, shooting range, signals, tuning playground, stress test, animated NPC, foot IK, euphoria showcase.

Requirements

  • Godot 4.7+
  • Jolt Physics (Project Settings > Physics > 3D > Physics Engine = "Jolt Physics")

Installation

  1. Copy the addons/kickback/ folder into your project's addons/ directory
  2. Enable the plugin: Project > Project Settings > Plugins > Kickback > Enable
  3. Verify Jolt Physics is active in Project Settings > Physics > 3D

Quick Start

1. Add Kickback to your character

Select your character node (must have a Skeleton3D child), then:

Project > Tools > "Add Kickback to Selected"

This adds the active-ragdoll node set — the full physics rig with springs (stagger, ragdoll, and recovery). The plugin auto-detects humanoid bones and wires the controller nodes.

2. Send hits from your game

# One-line hit detection + routing:
func _unhandled_input(event: InputEvent) -> void:
    if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
        var profile := ImpactProfile.create_bullet()
        KickbackRaycast.shoot_from_camera(get_viewport(), event.position, profile)

Or manual routing:

var kickback: KickbackCharacter = character.get_node("KickbackCharacter")
kickback.receive_hit(hit_collider, hit_direction, hit_position, profile)

3. Impact profiles

ImpactProfile.create_bullet()     # Low impulse, high reduction, fast recovery
ImpactProfile.create_shotgun()    # Wide spread, 40% ragdoll chance
ImpactProfile.create_explosion()  # Massive impulse, upward bias, near-certain ragdoll
ImpactProfile.create_melee()      # Strong transfer, moderate ragdoll chance
ImpactProfile.create_arrow()      # Localized, moderate impulse

Or use the preset .tres files in addons/kickback/presets/.

4. Customize

  • Force stagger: kickback_character.trigger_stagger(hit_direction)
  • Force ragdoll: kickback_character.trigger_ragdoll()
  • Persistent ragdoll (death): kickback_character.set_persistent(true) — revive with set_persistent(false)
  • Protected bones: set ragdoll_tuning.protected_bones to keep legs (or any bones) animated during hits
  • Query state: is_ragdolled(), is_staggering(), get_active_state_name()
  • Advanced control: var active_controller = kickback_character.get_active_controller() — the ActiveRagdollController (or null), for the queries below
  • Query balance: active_controller.get_balance_ratio() — 0.0 = balanced, 1.0+ = off-balance
  • Query fatigue: active_controller.get_fatigue() — 0.0 = fresh, 1.0 = exhausted
  • Reset fatigue: active_controller.reset_fatigue() — on healing or respawn
  • Query hit streak: active_controller.get_hit_streak() — rapid consecutive hit count
  • Query pain: active_controller.get_pain() — cumulative damage level
  • Pre-hit flinch: kickback_character.anticipate_threat(direction, urgency) — defensive lean before impact
  • Query injuries: active_controller.get_injury(rig_name) — per-bone injury level
  • Reset injuries: active_controller.reset_injuries() — heal all injuries
  • Different skeleton? Auto-detects, or create a RagdollProfile manually
  • Different physics feel? Create a RagdollTuning resource
  • Find all characters: KickbackCharacter.find_all(scene_root)

Architecture

Character (Node3D)
├── KickbackCharacter (coordinator — detects mode, routes hits)
├── PhysicsRigBuilder (creates 16 RigidBody3D + 15 joints)
├── PhysicsRigSync (SkeletonModifier3D: physics → skeleton)
├── SpringResolver (animation → physics velocity springs)
└── ActiveRagdollController (NORMAL/STAGGER/RAGDOLL/GETTING_UP/PERSISTENT)

Active Ragdoll signals (connect for custom animation handling):

  • stagger_started(hit_direction) — character wobbles, stays on feet
  • stagger_finished() — recovered from stagger
  • ragdoll_started() — full ragdoll triggered
  • recovery_started(face_up) — getting up from ragdoll
  • recovery_finished() — fully recovered
  • hit_absorbed(rig_name, strength) — light hit, no state change
  • balance_changed(ratio) — CoM balance ratio during stagger (0.0 = balanced, 1.0 = falling)
  • fatigue_changed(level) — fatigue from repeated hits (0.0 = fresh, 1.0 = exhausted)
  • recovery_interrupted() — hit during get-up knocked character back down
  • pain_changed(level) — cumulative pain from sustained hits (0.0-1.0)
  • threat_anticipated(direction, urgency) — anticipate_threat() was called
  • region_injured(rig_name, severity) — bone sustained persistent injury

Optional component: add a PhysicsCollisionMonitor next to the controllers to emit body_impact(bone_name, velocity, contact_body) whenever ragdoll bodies strike the environment — handy for impact SFX, decals, or scoring. See INTEGRATION.md.

Important: All root movement and rotation must happen in _physics_process, not _process, to stay in sync with the spring resolver.

Demo Scenes

Run any scene from demo/ to see the plugin in action:

Scene What it shows
demo.tscn Kickback active ragdoll vs Godot's built-in PhysicalBoneSimulator3D
shooting_range.tscn FPS controller, 5 weapon profiles + ball-throw alt-fire (RMB)
tuning_playground.tscn Tuning Lab: Tank/Standard/Loose/Fragile/Protected presets + a Custom character with live sliders
signal_showcase.tscn Floating popups + log showing every signal
stress_test.tscn 20 characters, mass ragdoll, budget system
animated_npc.tscn Signal-driven NPC: patrol, hit, recover, resume
foot_ik_demo.tscn Foot IK on vs off over varied terrain — planting + anti-slide
euphoria_showcase.tscn Active resistance, stagger sway, pain, momentum, injuries

Collision Layers

Layer Purpose Used by
2 Environment StaticBody3D (floors, walls)
4 Active ragdoll bodies PhysicsRigBuilder
5 Godot built-in ragdoll bones (comparison demo only) PhysicalBoneSimulator3D

Use KickbackRaycast which targets the active-ragdoll layer (4) automatically.

Debug Tools

  • F3 — Cycle debug gizmos: Off → Dots → Wireframe + state → Full dashboard (panels, CoM, velocity)

    Debug gizmos — bone dots, wireframe, full dashboard with CoM and velocity vectors
  • Inspector — Select KickbackCharacter to see setup status and validation

  • Visible Collision Shapes (Debug menu) — See ragdoll collision shapes

License

MIT

About

Physics-based reactive characters for Godot 4.6+ (Euphoria-like hit reactions)

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors