# 1. Layer Stacks and Avatar Masks Deep Dive Part of [[Animation Advanced]]. Next: [[2.Sync Layers Write Defaults and Interruption]]. Fundamentals preview: [[4.Layers Masks Root Motion and Events]]. **Docs:** [Animation Layers (6000.5)](https://docs.unity3d.com/6000.5/Documentation/Manual/AnimationLayers.html) ## 1.1 Why stacks matter A single full-body state machine does not scale to: locomotion + upper-body aim + gesture + hit-react additive. Layers let each concern own a weight and an **Avatar Mask**. Gameplay code ([[Enemy AI State Machine]]) sets weights/triggers; the Animator blends the body. Typical stack (Override unless noted): | Index | Name | Mask | Role | |---|---|---|---| | 0 | Base | (none / full) | Locomotion, jump, death | | 1 | UpperBody | Arms+Head+Chest | Aim, reload, use, wave | | 2 | AdditiveHit | Chest+Head (Additive) | Hit reacts layered on top | | 3 | Face | Head only *(or jaw bones in mask)* | Visemes / brows (optional) | ## 1.2 Override vs Additive (precise) - **Override** — replaces masked curves from lower layers. - **Additive** — adds deltas. Docs: additive clips must contain the **same properties** as previous layers for success. Author additive clips from a clean reference pose (often T-pose or idle). ```csharp using UnityEngine; /// <summary> /// Smoothly weight an upper-body Override layer. /// NOT compiled in Unity. /// </summary> [RequireComponent(typeof(Animator))] public sealed class LayerWeightDriver : MonoBehaviour { [SerializeField] int upperBodyLayer = 1; [SerializeField] float damp = 10f; float _target; Animator _anim; void Awake() => _anim = GetComponent<Animator>(); public void SetUpperBody(float weight01) => _target = Mathf.Clamp01(weight01); void Update() { float w = _anim.GetLayerWeight(upperBodyLayer); w = Mathf.MoveTowards(w, _target, damp * Time.deltaTime); _anim.SetLayerWeight(upperBodyLayer, w); } } ``` ## 1.3 Avatar Mask authoring edge cases 1. **Humanoid body mask vs Transform mask** — Humanoid checkboxes for body regions; Transform mask for Generic / extra bones (weapons, cloth, tails). Mixing incorrectly leaves a weapon bone driven by base locomotion. 2. **Root / hips in upper-body mask** — If hips are included on an upper-body Override, you will fight locomotion root / spine. Keep Root/Hips **off** for aim/reload layers unless you intentionally own them. 3. **Left/Right hand only** — Fine for one-handed gestures; two-handed rifles usually need both Arms + Spine upper. 4. **IK Pass per layer** — `OnAnimatorIK(layerIndex)` only runs for layers with **IK Pass** enabled ([[5.Animation Rigging and Script IK]]). Upper-body aim that uses script IK needs IK Pass on that layer. 5. **Mask shared assets** — One mask asset reused across controllers is good; mutating it affects every layer that references it. ## 1.4 Weight authority Pick **one** owner for each layer weight: - Code brain (preferred for gameplay) — [[Architecture and Code Patterns]] - Animator transitions that blend into Empty states at weight 0 *(fragile)* - Timeline Animation Override tracks ([[Timeline Basics]]) during cutscenes — restore weights on exit ```csharp using UnityEngine; /// <summary> /// Example: aim layer on while aiming, gesture layer pulses for a one-shot. /// NOT compiled in Unity. /// </summary> public sealed class CombatLayerBrain : MonoBehaviour { [SerializeField] Animator animator; [SerializeField] int aimLayer = 1; [SerializeField] int gestureLayer = 2; [SerializeField] LayerWeightDriver aimDriver; // optional smoother static readonly int AimHash = Animator.StringToHash("Aim"); static readonly int GestureHash = Animator.StringToHash("Gesture"); public void SetAiming(bool aiming) { animator.SetBool(AimHash, aiming); if (aimDriver != null) aimDriver.SetUpperBody(aiming ? 1f : 0f); else animator.SetLayerWeight(aimLayer, aiming ? 1f : 0f); } public void PlayGesture() { animator.SetLayerWeight(gestureLayer, 1f); animator.SetTrigger(GestureHash); // Return weight to 0 via StateMachineBehaviour OnStateExit or a timed coroutine. } } ``` ## 1.5 Empty states as "passthrough" On an Override layer, an **Empty** state (no motion) with Write Defaults configured carefully lets lower layers show through when weight is 1 but the empty state writes nothing useful — many teams instead drop **layer weight to 0** and keep a neutral idle on the layer. Pick one convention and stick to it (see part 2 Write Defaults). ## Unverified - Exact Transform-mask UX for your FBX extra bones. - Whether your character's spine division (Chest vs UpperChest) matches the Humanoid mapping you expect for aim masks.