# 5. Sub-State Machines for Combat / Locomotion Part of [[Animation Advanced]]. Prev: [[4.MatchTarget CrossFade Rebind OverrideController]]. Next: [[6.Animation Events Reliable Patterns]]. Intro: [[2.States Transitions and Parameters]]. Brain: [[Enemy AI State Machine]] · [[Game Programming Patterns (Review)]]. ## 5.1 Principle **Gameplay State** (C# / [[Enemy AI State Machine]]) ≠ **Animator Sub-State Machine**. The brain decides *intent* (Locomotion, AttackWindup, Hitstun). The Animator mirrors with clean Sub-State Machines and a small parameter surface. Avoid: dozens of Any-State → X transitions. Prefer: entry/exit ports on Sub-State Machines + a few gate bools/triggers. ## 5.2 Suggested graph shape ``` Base Layer ├── Locomotion (Sub-State Machine) │ Idle ⇄ Move (Blend Tree) ⇄ Sprint │ → Jump / Fall (optional nested) ├── Combat (Sub-State Machine) │ Windup → Active → Recovery → (exit to Locomotion) │ Charged variants… ├── HitReact (Sub-State Machine) │ Light / Heavy / Knockdown └── Death (state or SSM) ``` Upper-body **Aim** lives on **layer 1** (part 1 / part 7), not inside Base Combat, so locomotion feet keep moving. ## 5.3 Parameter budget Keep the Animator API small; expand in code: | Param | Type | Owner | |---|---|---| | `Speed` / `MoveX`/`MoveY` | float | Locomotion | | `IsGrounded` | bool | Mover | | `Attack` | trigger | Combat brain | | `AttackId` | int | Which attack clip/branch | | `Hit` | trigger | Damage pipeline | | `HitDir` | float/int | React branch | | `InCombat` | bool | Gates SSM entry | | `CanCancel` | bool | Set by events (part 6) | | `Die` | trigger | | ## 5.4 Entry / exit hygiene - **Enter Combat SSM** via `InCombat` or `Attack` from Locomotion only when grounded / not dying. - **Exit** Combat only from Recovery (or cancel window) back to Locomotion — not from Active unless design allows. - **HitReact** can interrupt Combat via ordered interruption or brain `CrossFade` into Hit SSM when hitstun applies. ```csharp using UnityEngine; /// <summary> /// Thin Animator façade — gameplay state machine calls this, not raw SetTrigger soup everywhere. /// NOT compiled in Unity. /// </summary> public sealed class AnimCombatFacade : MonoBehaviour { [SerializeField] Animator animator; static readonly int SpeedHash = Animator.StringToHash("Speed"); static readonly int AttackHash = Animator.StringToHash("Attack"); static readonly int AttackIdHash = Animator.StringToHash("AttackId"); static readonly int HitHash = Animator.StringToHash("Hit"); static readonly int InCombatHash = Animator.StringToHash("InCombat"); static readonly int CanCancelHash = Animator.StringToHash("CanCancel"); static readonly int DieHash = Animator.StringToHash("Die"); public void SetSpeed(float speed) => animator.SetFloat(SpeedHash, speed); public void RequestAttack(int attackId) { animator.SetInteger(AttackIdHash, attackId); animator.SetBool(InCombatHash, true); animator.SetTrigger(AttackHash); } public void RequestHit() { animator.SetTrigger(HitHash); } public void RequestDeath() { animator.ResetTrigger(AttackHash); animator.SetTrigger(DieHash); } public bool CanCancel => animator.GetBool(CanCancelHash); // Animation Events → public void Anim_OpenCancel() => animator.SetBool(CanCancelHash, true); public void Anim_CloseCancel() => animator.SetBool(CanCancelHash, false); public void Anim_CombatExit() => animator.SetBool(InCombatHash, false); } ``` ## 5.5 Interruptible transitions (combat) 1. Windup: usually **not** interruptible by another attack; **is** interruptible by Hit. 2. Active (commit): almost nothing cancels except Hit/Death. 3. Recovery: `CanCancel` true → transition to new Attack or Locomotion. Author transitions with Interruption Source matching that policy (part 2). Brain may additionally `CrossFade` when `CanCancel` and input buffered. ## 5.6 Nested SSMs vs more layers | Prefer SSM nesting when… | Prefer new layer when… | |---|---| | Same body region, mutually exclusive modes | Simultaneous body regions (feet + arms) | | One clip owns full body | Masked upper-body aim over locomotion | | Clarity of mode graph | Independent weights | Readability for players ([[Level Up! (Review)]]) comes from clear poses — architecture should make those poses reachable, not clever. ## Unverified - Exact Sub-State Machine entry-state portal UI clicks in your Editor version (workflow stable; labels may differ). See also (added 2026-11-10): [[Combat Feel and Hit Feedback]] - attack strings, hitboxes, hit-stop and dodge on top of this graph.