Layers and Blending
Layers are the foundation of Motix's animation blending system. Every animation belongs to exactly one layer. Layers determine which animations can play simultaneously, how their weights combine, and in what order they are applied to the rig.
What Layers Do
Without layers, only one animation could play at a time. With layers, you can have a locomotion animation on one layer and a weapon animation on another. Both contribute to the final pose independently.
Each layer has:
- A name, used in animation configs and state definitions
- An order, which determines evaluation priority
- A base weight, the default contribution value when active
- A lerp rate, controlling how quickly weight changes interpolate
- Optional flags for additive blending and isolation
Defining Layers
Define layers with :Layer(name) on the builder:
:Layer("Base")
:Order(0)
:BaseWeight(1.0)
:LerpRate(8.0)
:Done()
:Layer("UpperBody")
:Order(1)
:BaseWeight(1.0)
:Additive(true)
:LerpRate(6.0)
:Done()
Every animation config must reference a layer that is defined in the same behavior:
:Animation("Run")
:AssetId("rbxassetid://RUN_ID")
:Layer("Base") -- must match a defined layer name
-- ...
:Done()
Layer Order
Order is an integer. Lower values are evaluated first. All orders must be unique per
behavior. Duplicate orders cause a build-time validation error.
Order determines which layer takes precedence in blending. A layer at order 1 can override
or blend on top of the layer at order 0.
:Layer("Base"):Order(0):Done() -- evaluated first
:Layer("UpperBody"):Order(1):Done() -- evaluated on top of Base
:Layer("Face"):Order(2):Done() -- evaluated on top of both
Weight and LerpRate
Each layer has a current weight and a target weight. Every frame, the current weight
interpolates toward the target at LerpRate units per second.
BaseWeight is the target weight when the layer is active (not suppressed). Setting
BaseWeight = 1.0 means the layer contributes fully when active.
LerpRate = 8.0 means the weight can move 8 units per second. A layer at weight 0 takes
roughly 0.125 seconds to reach full weight. Set LerpRate = math.huge for an instant snap.
:Layer("Overlay")
:Order(2)
:BaseWeight(1.0)
:LerpRate(math.huge) -- instant weight changes
:Done()
Additive Layers
When Additive = true, the layer composes with lower layers rather than replacing them.
Use additive layers for animations that should augment the base pose: upper-body recoil,
facial expressions, procedural lean.
:Layer("UpperBody")
:Order(1)
:Additive(true)
:BaseWeight(1.0)
:LerpRate(6.0)
:Done()
Animations assigned to an additive layer should themselves be marked additive:
:Animation("RecoilOverlay")
:AssetId("rbxassetid://RECOIL_ID")
:Layer("UpperBody")
:Additive(true)
:Looped(false)
:Done()
Isolated Layers
When Isolated = true, the layer does not interact with other layers during blending.
Isolation is useful for layers that should operate completely independently of the rest
of the rig.
State Control Over Layers
States activate and suppress layers. This is the primary way layer weights change at runtime.
When a state is entered:
ActiveLayersets the layer'sTargetWeightto itsBaseWeightSuppressLayersets the layer'sTargetWeightto0
Layers not mentioned by either directive are not touched during the transition.
:State("Combat")
:ActiveLayer("Base")
:ActiveLayer("UpperBody")
:SuppressLayer("Face")
-- ...
:Done()
:State("Cutscene")
:ActiveLayer("Base")
:ActiveLayer("Face")
:SuppressLayer("UpperBody")
-- ...
:Done()
When transitioning from "Combat" to "Cutscene", "UpperBody" fades to zero and "Face"
fades in to its base weight. "Base" stays at its base weight throughout.
Conflicts Within a Layer
Animations on the same layer compete with each other. Only one non-group animation can play on a given layer at a time. When a new animation requests the same layer as a playing animation, the conflict resolver compares their priorities.
Higher priority wins. Lower priority animations are stopped. If the priorities are equal, the incoming animation replaces the incumbent.
Use exclusive groups when you need finer control over which animations within a layer can replace each other.
A Practical Setup
A typical game character might have three layers:
| Layer | Order | Additive | Purpose |
|---|---|---|---|
Base | 0 | false | Full-body locomotion: idle, walk, run, jump |
UpperBody | 1 | true | Weapon animations: aim, fire, reload |
Face | 2 | true | Facial expressions, lip sync |
:Layer("Base"):Order(0):BaseWeight(1.0):LerpRate(8.0):Done()
:Layer("UpperBody"):Order(1):BaseWeight(1.0):Additive(true):LerpRate(6.0):Done()
:Layer("Face"):Order(2):BaseWeight(1.0):Additive(true):LerpRate(4.0):Done()
With this setup, a character can run (Base), hold their weapon ready (UpperBody), and emote (Face) simultaneously, each layer contributing independently to the final pose.