Design

Hit Stop and Impact Frames: Small Tricks, Big Feel

A few frames of freeze on contact is one of the cheapest ways to make a hit land. Here is how to time it, scope it and build it in Unity without breaking everything else that uses time.

Vectra Play 5 min read
A game developer scrubbing frame by frame through a combat animation on a monitor

Hit stop is a freeze of a few frames at the moment two things collide. It gives the player's eye time to register the hit and makes the blow feel heavy. Good hit stop game feel comes from three choices: how long you freeze, what you freeze, and what you layer on top, like a flash or camera kick.

Why a pause makes a hit feel stronger

Fast action is hard to read. If a sword passes through an enemy in one frame, the brain barely sees contact. Freezing for a moment fixes that.

It also borrows from animation. A pose held at the peak of an impact reads as force. Fighting games have used this for decades, and it works just as well in a mobile brawler or a physics puzzler.

Hit stop is cheap to build and easy to overdo. The trick is in the tuning.

How long to freeze

There is no single right number, and you should tune by feel on the target device. As a starting point many devs work in frames at 60 fps.

Hit typeStarting freezeNotes
Light, rapid hits2 to 4 framesToo long and combos feel sticky
Standard hit4 to 8 framesThe workhorse value
Heavy or finishing hit8 to 15 framesPair with shake or flash
Boss kill or big momentLonger, with slow motion outUse rarely so it stays special

Scale freeze length with damage or weight, not as a fixed value. A heavy hit that freezes the same as a jab loses its punch.

What to freeze

This decision matters more than the duration.

For most small action games, global freeze on heavy hits and local freeze on light ones is a good mix.

Building it in Unity

The simplest global version uses Time.timeScale and waits in unscaled time, so the coroutine itself does not freeze.

IEnumerator HitStop(float seconds) {
    Time.timeScale = 0f;
    yield return new WaitForSecondsRealtime(seconds);
    Time.timeScale = 1f;
}

Guard against overlapping calls. If two hits land at once, keep the longer freeze rather than restarting, or the second call can cut the first short. Store an end time in unscaled seconds and only extend it.

Things that break when you freeze time

Freezing time scale stops anything that reads Time.deltaTime. Check these before you ship.

  1. UI animations should use unscaled time. On an Animator, set Update Mode to Unscaled Time.
  2. Tweens in DOTween or LeanTween need their unscaled or independent update option for UI.
  3. Input should still register during the freeze so the next attack can buffer.
  4. Audio keeps playing, which is usually what you want. The hit sound should fire at the start of the freeze.
  5. Physics pauses with time scale, so any knockback you apply resumes cleanly afterward.

For a local freeze, set animator.speed = 0 on the attacker and target, then restore it. Pause their particle systems too if you want the effect to match.

Layering impact frames on top

Hit stop does most of the work, and a few extra layers finish it. Add them one at a time and test each.

Juice should tell the player something. If a layer does not help them read the hit, cut it.

Our frame-by-frame teardown of game feel shows how these layers stack in a shipped game.

Mobile-specific notes

On phones, players often hold the device further away and play in short bursts. Hits need to read on a small screen.

Lean on flash and squash, which read well at small sizes, and keep camera shake modest so the screen stays readable. Offer a reduce motion toggle in settings that cuts shake and flash, and keep the freeze, which does not cause discomfort.

Test on a real phone at the real frame rate. A freeze tuned at 144 fps in the editor feels different at 30 fps on a budget Android.

What we would do

We would add hit stop first, before any other juice, and tune it alone until the hits feel right with placeholder art. Then we would add flash, then shake, then particles, testing after each one.

We would keep every value in a ScriptableObject so a designer can tune hits without opening code. And we would always check the pause menu and UI after adding a global freeze, because that is where it breaks first.

The short version

If your combat feels floaty and you want a second opinion on the feel, drop us a line.

Related reading: Making a 2D Game Feel Good: Camera, Tweening, and Timing, Input Handling for Mobile: Touch, Drag, and the Feel of Control

#Design#Game Design#Unity#Indie#Development
Your turn

Got a game idea? We build it.

You bring the concept. We design, build, test and launch it, and you own 100% of the finished game.

Share Your Game Idea  →