[Tutorial] Hit-stop and screen shake in Godot 4 (autoload + trauma camera, MIT)

Hi all,

I wrote up the hit-stop and screen shake setup I use in Godot 4, mostly because the obvious versions have two traps: a time_scale freeze that never ends (the end timer is slowed too), and shake built on randf() that looks like static.

Disclosure: I make and sell Godot effect packs, and the full write-up ends with a pointer to Hitfeel Kit (a free Lite and a paid pack, both on itch.io). The code here is free (MIT) and does not need either. I also used an AI assistant (Claude) for part of the code and the drafting, and I ran and checked everything myself.

Overview

  • HitStop autoload: sets Engine.time_scale low and ends the freeze with create_timer(0.005, true, false, true), where the last argument is ignore_time_scale. It keeps a real-time end timestamp, so overlapping hits extend the freeze instead of restoring speed early.
  • ScreenShake (extends Camera2D): a decaying trauma value, displacement of trauma^power times simplex noise for offset and roll, and delta divided by Engine.time_scale so the shake keeps animating during the freeze.
  • Optional canvas_item flash shader (mix to a solid colour, alpha preserved) driven by a tween.

Usage:

HitStop.hit_stop(0.08)        # light hit; ~0.14 for heavy
$Camera2D.add_trauma(0.4)     # light hit; ~0.7 for heavy

Parameters worth tweaking

Hit-stop 0.04-0.08 s (light) to 0.10-0.18 s (heavy); freeze_scale 0.0-0.2; shake power 2-3, decay 1.0-2.5, noise_speed 30-100+. Keep max_roll small, and add an accessibility setting for shake.

Full tutorial

The complete code for all three files, an explanation of how each works, and a list of pitfalls: Hit-stop and screen shake in Godot 4 - Hitfeel Kit - Hit Stop, Screen Shake & Damage Numbers for Godot 4 by inkharbor

What I tested

Godot 4.7-stable on Linux, Compatibility/GL via xvfb-run --rendering-driver opengl3 (software GL). The project imports cleanly; a script checked overlapping freezes (about 0.2 s real time, time_scale back to exactly 1.0), non-zero shake offset during the freeze, trauma decaying to zero, and that the shader compiles and accepts its uniform.

I did not test how it feels in a real game, Forward+/Mobile, other platforms, real GPUs, audio behaviour or 3D cameras. Feedback from people who have, especially on audio during time_scale changes, is welcome.