# 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.