Action RPG: Systems Engineering

Overcoming animation pipeline challenges and implementing scalable combat logic in an AAA-scale Unity prototype.

Engine: Unity (C#)
System: Event-driven melee combat system with hybrid root-motion control and modular animation pipeline
Architecture: Component-based gameplay architecture separating input, animation, combat logic, and physics ownership for scalability
Unity C# Animation Retargeting Root Motion Handling Event Architecture

1. Managing Complexity & Scope

This was my first project with an AAA-scale scope ambition. The sheer number of interacting systems (Movement, Combat, UI, Quests) quickly led to a tightly coupled player controller that became a classic "God Class", making debugging and iteration increasingly fragile.

The Solution: I refactored the monolith into modular components by separating PlayerInput from the ActionController and introducing a dedicated AnimationInterface. This architectural shift reinforced the importance of the Single Responsibility Principle in large-scale gameplay systems.

2. The Animation Pipeline Struggle

Integrating Mixamo assets exposed several systemic animation issues, including character sliding ("ice skating"), T-poses, and mesh deformation during runtime.

The Root Cause: A conflict between Root Motion and code-driven velocity. Some animations translated the root bone while others were strictly "In-Place", resulting in competing movement calculations. Additionally, inconsistent rig definitions introduced bone mapping errors.

The Fix:

3. Event-Driven Combat Architecture

To eliminate "floating hits"—where enemies took damage before visual contact—I implemented an Animation Event–driven combat pipeline.

stateDiagram-v2 [*] --> Idle Idle --> Attack: Input state Attack { [*] --> WindUp WindUp --> DamageActive: Anim Event (OpenHitbox) DamageActive --> DamageEnd: Anim Event (CloseHitbox) } DamageActive --> ApplyDamage: OnCollisionEnter DamageEnd --> Idle

// Ensuring damage matches visuals exactly
public void OpenHitbox()
{
    // Triggered via Animation Event at the exact swing frame
    weaponCollider.enabled = true;

    // Temporarily allow animation-driven motion
    animator.applyRootMotion = true;
}

public void CloseHitbox()
{
    weaponCollider.enabled = false;

    // Return full control to the physics system
    animator.applyRootMotion = false;
}
        

Outcome