Combat Systems and Interaction Mechanics Design

Our video game development company runs independent projects, jointly creates games with the client and provides additional operational services. Expertise of our team allows us to cover all gaming platforms and develop an amazing product that matches the customer’s vision and players preferences.
Showing 1 of 1 servicesAll 242 services
Combat Systems and Interaction Mechanics Design
Complex
from 1 week to 1 month
FAQ
Our competencies
What are the stages of Game Development?
Latest works
  • image_games_mortal_motors_495_0.webp
    Game development for Mortal Motors
    663
  • image_games_a_turnbased_strategy_game_set_in_a_fantasy_setting_with_fire_and_sword_603_0.webp
    A turn-based strategy game set in a fantasy setting, With Fire and Sword
    859
  • image_games_second_team_604_0.webp
    Game development for the company Second term
    490
  • image_games_phoenix_ii_606_0.webp
    3D animation - teaser for the game Phoenix 2.
    533

Designing Combat Systems and Interaction Mechanics

A combat system doesn't break where you design it—it breaks at the junction between animation, hitbox, and damage logic. A typical scenario: a designer places the attack window at Animation Event frame 12, the programmer reads it in OnAttackHit(), and QA finds that the hit passes through the enemy at fps below 30—because Physics.OverlapSphere is called exactly once at the moment of the event, and the enemy collider doesn't overlap with the hitbox between frames.

Hitbox System Architecture

A professional implementation separates hurtbox (area you can hit) and hitbox (area the character attacks with). Both are separate colliders on child objects, managed via Hurtbox : MonoBehaviour and Hitbox : MonoBehaviour components.

The hitbox is activated not via SetActive(), but through toggling isTrigger and layer—this is cheaper performance-wise for frequent on/off. A single attack hitbox must hit each hurtbox only once: this is controlled via HashSet<int> with InstanceID of already-hit targets, which is cleared when the hitbox deactivates.

For melee weapons with fast movements, OverlapSphere per frame isn't enough. More reliable is Physics.CapsuleCast from the weapon position on the previous frame to the current one—this catches targets in the blade's trajectory between frames. previousPosition is stored in LateUpdate() of the previous frame.

Managing Combat States

The combat state machine is not an Animator State Machine. Animator manages the visuals; game logic lives in a separate CombatStateMachine. States: Idle, Attacking, Recovering, Staggered, Blocking, Parrying. Each state is a separate class with Enter(), Update(), Exit().

Attack cancel priority is one of the most complex parts. In fighting games and action-RPGs, the player should be able to cancel part of the attack animation into a dash or the next hit. This is implemented via cancelWindows[]—an array of structures with startFrame, endFrame, allowedCancels. When the normalized Animator time falls within a window, the canCancel flag is raised, and CombatStateMachine accepts new input.

Interaction Systems: Interactive Objects and Dialogs

The interaction component is built on the Interactable / Interactor scheme. IInteractable is an interface with the Interact(GameObject interactor) method. InteractorComponent on the player holds List<IInteractable> within range, updated via OnTriggerEnter/Exit. On button press, closest.Interact(gameObject) is called.

A common mistake is implementing interaction via Raycast in Update() every frame. This is both unnecessary computation and priority problems with multiple objects in the ray. A trigger zone with OverlapSphere checked every 0.1 seconds via InvokeRepeating is cheaper and more reliable.

For dialog interactions, an event queue is important. If the player presses the button again during dialog, the next Interact shouldn't be processed until the current dialog closes. The isInteracting flag in InteractorComponent blocks new interactions—and is cleared via the OnInteractionComplete event.

Balancing Responsiveness and Readability

Feedback on hit is critical for combat feel. A minimal set: hitpause (stop the attacker's animation for 2–4 frames on hit), screen shake via CinemachineImpulse, sound effect with pitch variation. Hitpause is implemented by temporarily setting animator.speed = 0 and not touching Time.timeScale—important if there's UI or other systems.

Damage numbers are a separate conversation. Floating text with TextMeshPro should be instantiated from a pool, not via Instantiate() every hit. In active combat with AoE attacks, without a pool you can easily get 50+ instantiations per second and GC spike.

Timeline Guidelines

Scale Components Timeframe
Basic Single attack, hurtbox/hitbox, HP component 3–6 days
Medium Combo system, block, parry, i-frames 2–3 weeks
Extended Multiple weapon types, abilities, status effects 4–6 weeks
Full system Network combat sync, rollback netcode 2–4 months

Design Process

We start with a state and transition table in a document—before writing code. Each state, each transition, condition, and priority. This uncovers conflicts at design stage: for example, what happens if the player takes damage while parrying—stagger or not?

Then—a prototype with placeholder animations (even cubes) to verify attack window timing and cancel system. Integration with real animations is the last stage, not the first.