hitbox/hurtbox timing in frame-data driven combat — how are you wiring this up without it becoming a mess?

108 views 3 replies

Building a melee combat system and the part giving me the most grief isn't the feel or the animation, it's the data pipeline for hitbox activation windows. I know what I want: on frame 8 of the swing, activate hurtbox A, deactivate on frame 14. Simple in concept. Nightmare in practice.

I started with hardcoded offsets in animation event callbacks, Unity's AnimationEvent at specific normalized time thresholds. This works until you tweak the animation timing and suddenly everything's shifted. Or until you want to adjust the active window by "just a couple frames" and realize you need to re-time events in the clip by hand, every time, forever.

I've since moved toward storing frame data externally. Each attack has an entry in a ScriptableObject with startup, active, and recovery frame counts, and hurtbox definitions are separate assets activated by the state machine based on those values. Decoupled from the clip itself. But now I'm fighting a different problem: the state machine needs to know the current animation frame to index into that data, and frame-accurate queries against the Animator are surprisingly annoying to get right, especially once you account for playback speed modifiers.

Things I'm still wrestling with:

  • Are you driving hitbox windows from animation events or from external frame data?
  • If external, how are you keeping the data in sync when an animator retimes an attack animation?
  • Has anyone built even a basic visual frame data editor? The spreadsheet workflow is genuinely killing me.

Also curious if anyone has tackled the hitstop problem. When you freeze the animation on hit, do you pause the hitbox window timer too, or does that break your combo linking? That one's been a headache. Every solution I try creates a new edge case.

The approach that's worked best for me: keep hitbox activation completely out of animation events and drive it off a frame-indexed data asset per attack. Each attack defines active windows as inclusive ranges (active: [[8, 14]]), and a dedicated system evaluates a discrete game-tick counter on every FixedUpdate to decide whether boxes are live.

The critical part is defining "frame" as a game-tick-aligned counter you control, not animation system time and not wall clock time. Once you have that, hitbox data is just data. Editable in a spreadsheet, loadable from JSON, diffable in version control. The animation plays; it doesn't own the gameplay timing. Mixing those concerns is where the mess comes from. Hitbox logic in animation events means gameplay state is embedded in animation assets, which creates a weird ownership problem between animators and combat programmers that nobody ever quite resolves.

Replying to QuantumDusk: solid approach, this is basically how traditional fighting game engines handle i...

the bone-space thing burned me hard early on too. i was storing offsets in root space and whenever an attack had root motion step-forward, the hitbox would lag behind by exactly the translation amount — felt like it was on a delay that scaled with how much the character moved. took way too long to diagnose because the hitbox looked roughly right in static tests. moved everything to the attack bone anchor and it just worked. seems so obvious in hindsight lol

Replying to TurboRay: The approach that's worked best for me: keep hitbox activation completely out of...

solid approach, this is basically how traditional fighting game engines handle it. one thing i'd add though: store hitbox offsets relative to a named bone anchor, not root or world space. found out the hard way when we rescaled an enemy mid-production and every hitbox was suddenly floating in the wrong position. frame-indexed data asset is clean, but bone-relative coords is what makes it actually resilient to iteration.

Moonjump
Forum Search Shader Sandbox
Sign In Register