Override Slots & Layers
TL;DR: The engine looks up specific clip override names on your avatar’s AnimatorOverrideController to drive emotes, toggles, sitting, and the death animation. It also references four animator layer name constants. While a legacy emote is playing, PlayerBase.LegacyEmoteCheck zeroes the LeftHand and RightHand layer weights so the hands don’t fight the emote.
Emote slots
Section titled “Emote slots”| Slot name | Default clip name | Role |
|---|---|---|
Emote1 | Wave | Default emote 1 |
Emote2 | Bow | Default emote 2 |
Emote3 | Die | Default emote 3 — also temporarily reused for the death animation override (see below) |
Emote4 | Backflip | Default emote 4 |
Emote5 | Point | Default emote 5 |
Emote6 | Sad | Default emote 6 |
Emote7 | Salute | Default emote 7 |
Emote8 | Dance | Default emote 8 |
The arrays are exposed as:
AvatarAnimatorManager.DefaultEmoteSlotNames— the slot names (whatAnimatorOverrideControllerlooks up).AvatarAnimatorManager.DefaultEmoteNames— the default clip names.
FindLegacyEmotesAndToggles() walks _originalOverrides at avatar setup. For every overridden slot it records the override clip name in _legacyOverrideEmoteNames, which the menu later surfaces as the user-facing emote name list (AvatarAnimatorManager.GetLegacyEmoteNames()).
Toggle slots
Section titled “Toggle slots”| Slot name | Index in toggle list |
|---|---|
ToggleDefault | 0 (Default) |
ToggleState1 | 1 |
ToggleState2 | 2 |
ToggleState3 | 3 |
ToggleState4 | 4 |
ToggleState5 | 5 |
ToggleState6 | 6 |
ToggleState7 | 7 |
The user-facing labels for these are pulled from the override clip names (AvatarAnimatorManager.GetLegacyToggleNames()), defaulting to Default, State 1..State 7.
The integer animator parameter Toggle selects the active slot — see Animator Parameters.
Special slots
Section titled “Special slots”LocSitting
Section titled “LocSitting”PlayerSetup.SetSittingAnimation(AnimationClip clip) calls:
base.AnimatorManager.SetOverrideAnimation("LocSitting", clip);Used by CVRSeat when a seat supplies a custom sit animation. There is no default clip with this name in the stock controller — the slot exists purely as an override target.
Emote3 (death animation)
Section titled “Emote3 (death animation)”PuppetMaster.PlayDeathAnimation(AnimationClip deathAnimation, float time) temporarily replaces the Emote3 override, plays it, then restores it:
PlayDeathAnimation(deathAnimation, time): _deathAnimationRunning = true; AnimatorManager.CancelEmote = true; AnimatorManager.Grounded = true; StartCoroutine(ProcessDeathAnimation(deathAnimation, time));
ProcessDeathAnimation: yield return new WaitForSeconds(0.05); AnimatorManager.SetOverrideAnimation("Emote3", deathAnimation); yield return new WaitForSeconds(0.05); AnimatorManager.Emote = 3; // play the slot StartCoroutine(ResetDeathAnimation(time));
ResetDeathAnimation: yield return new WaitForSeconds(time); AnimatorManager.CancelEmote = true; yield return new WaitForSeconds(0.05); AnimatorManager.RestoreOverrideAnimation("Emote3"); _deathAnimationRunning = false; yield return new WaitForSeconds(0.05); AnimatorManager.CancelEmote = true; // belt-and-bracesIf you author your own Emote3 (“Die”) override, that override is what’s restored when the death playback ends. The death animation clip itself is supplied by the world via the combat system, not by the avatar.
Animator layer name constants
Section titled “Animator layer name constants”AvatarDefinitions declares four layer name constants the runtime references:
public const string LOCOMOTION_EMOTES_LAYER_NAME = "Locomotion/Emotes";public const string HAND_LEFT_LAYER_NAME = "LeftHand";public const string HAND_RIGHT_LAYER_NAME = "RightHand";public const string TOGGLES_LAYER_NAME = "Toggles";Toggles is referenced as a constant but never re-weighted by the runtime — it exists for the default avatar controller and override workflows.
Legacy emote layer-weight gating
Section titled “Legacy emote layer-weight gating”PlayerBase.LegacyEmoteCheck() runs every late-update on every loaded avatar. It calls AnimatorManager.IsLegacyEmotePlaying() and toggles the hand layer weights:
private void LegacyEmoteCheck(){ bool flag = AnimatorManager.IsLegacyEmotePlaying(); if (flag && !IsEmotePlaying) { AnimatorManager.SetLayerWeight("LeftHand", 0f); AnimatorManager.SetLayerWeight("RightHand", 0f); IsEmotePlaying = true; } else if (!flag && IsEmotePlaying) { AnimatorManager.SetLayerWeight("LeftHand", 1f); AnimatorManager.SetLayerWeight("RightHand", 1f); IsEmotePlaying = false; }}IsLegacyEmotePlaying() checks the current clip on the Locomotion/Emotes layer and returns true if the clip name contains Emote or matches one of the override emote names. This means any emote in _legacyOverrideEmoteNames (your custom emotes too) will gate the hand layers.
If you want a non-emote clip on the Locomotion/Emotes layer that should not zero the hand layers, give the clip a name that does not contain Emote and is not in the override list — but practically this is brittle. The cleaner workaround is to put the clip on a different layer.