Skip to main content

FAQ

Answers to the questions that come up most often.


General

What is Motix?

Motix is an animation controller system for Roblox. It provides a typed fluent builder for defining animation behaviors, a multi-layer blending engine with interpolated weights, a predicate-driven state machine for automatic state transitions, exclusive animation groups for mutual exclusion, and MotixNet: a full network layer for replicating animation state across server and client.


Is Motix free?

Yes. MIT license. Use it however you want, commercial or otherwise.


What version is this?

This documentation covers Motix V1.0.0.


Does Motix work on the client, the server, or both?

Both. Motix.new() runs on either environment and connects to the appropriate RunService event automatically: RenderStepped on the client, Heartbeat on the server. On the server, animation tracks are not loaded or played. The server tracks animation state logically for network replication purposes.


Setup

Where does the Motix folder go?

ReplicatedStorage. Both client and server need to require it.


Why does AnimationController.new() throw an error on first call?

AnimationRegistry must be initialized before any controller is created. Call AnimationRegistry.GetInstance():Init(configs) at startup, before any call to Motix.new().


Do I need one controller or many?

One per character or entity that plays animations independently. A player character, an NPC, and a vehicle would each have their own controller. Controllers do not share state.


Can I use Motix without MotixNet?

Yes. MotixNet is entirely optional. Motix.new() works on its own. Handle your own networking and call Controller:Play() from wherever makes sense in your architecture.


Animations and Behaviors

What's the difference between BehaviorBuilder and raw config tables?

BehaviorBuilder gives you typed setters, build-time validation, and a frozen result. Raw tables passed directly to AnimationRegistry:Init() work as well but have no type safety and no validation until Init is called. The builder is the recommended path.


What does :Build() return if validation fails?

nil. All validation errors are collected and logged together so every problem is reported at once. Check the Output window for the full error list.


What is CanInterrupt?

When CanInterrupt is false, the animation cannot be stopped or replaced by a lower-priority animation while it is playing. Higher-priority group members can still override it.


What is MinDuration?

The minimum number of seconds the animation must play before it can be interrupted by another animation in the same group. The animation is always allowed to complete naturally; this only affects early interruption from group conflict resolution.


What is Additive on an animation config?

When true, the animation track is played in additive blending mode. Additive animations compose with other tracks rather than replacing them. Typically paired with a layer that is also marked additive.


How do I play animations with a given tag?

Use Controller:PlayTag(tag). This calls Play on every animation registered under that tag. Tags are defined with :Tag("tagname") or :Tags({ "tag1", "tag2" }) in the builder.


Layers

What is a layer?

A layer is a named slot that groups animations by their blending context. Animations on the same layer compete with each other. Animations on different layers blend together. Every animation must be assigned to a layer.


What is BaseWeight?

The default weight of the layer when it is active. Weights range from 0 to 1. A weight of 0 means no contribution from that layer. State transitions set layers to their base weight when they become active and to 0 when they are suppressed.


What is LerpRate?

The speed at which the layer weight interpolates toward its target value, in units per second. Higher values snap faster. Set to math.huge for an instant weight change without lerping.


What is Additive on a layer?

When true, the layer composes with lower layers rather than replacing them. Use this for upper-body overlays like weapon animations that should play on top of locomotion.


What is Isolated?

When true, animations on this layer do not affect other layers during blending. Isolation is useful for layers that should operate completely independently of the rest of the rig.


What is Order?

An integer that determines layer priority during blending. Lower values are evaluated first. Every layer in a behavior must have a unique order. Duplicate orders cause a validation error at Build time.


States and Transitions

What is the state machine?

The state machine is a finite state machine built into every AnimationController. It evaluates predicate functions every frame and automatically transitions between states when conditions are met. Transitions can also be triggered manually with RequestStateTransition.


What happens if two transitions fire simultaneously?

Transitions have a Priority value. When multiple transitions are eligible in the same frame, the highest-priority one wins. If priorities are equal, the first declared transition wins.


What happens if I call RequestStateTransition while a predicate transition is also ready?

Manual transitions queued via RequestStateTransition take precedence over predicate transitions within the same frame. Among multiple manual requests, the highest priority wins.


Can I have a state with no transitions?

Yes. States with no transitions are terminal states. The state machine stays in them indefinitely until RequestStateTransition is called. Terminal states do not evaluate predicates.


What are entry and exit actions?

Actions defined with :OnEntry() and :OnExit(). Entry actions run when the state becomes active. Exit actions run when the state is left. Actions can play animations, stop animations, or stop entire groups.


What is ActiveLayer?

A layer listed as ActiveLayer in a state has its weight set to its BaseWeight when the state becomes active. This is the standard way to enable a layer for a state.


What is SuppressLayer?

A layer listed as SuppressLayer in a state has its weight set to 0 when the state becomes active. Use this to disable layers that are not relevant during a particular state, such as suppressing a full-body layer during a vaulting animation.


Networking

Do I have to register animations in the same order on client and server?

Yes, strictly. Intents carry only a compact hash derived from registration order. If the orders differ between server and client, every intent is rejected as UnknownAnimHash. Enforce this by requiring the same shared ModuleScript on both sides and never registering conditionally.


What does RateLimited mean?

The player sent intents faster than TokensPerSecond allows. The server uses a token bucket: tokens refill at TokensPerSecond per second and allow burst up to BurstLimit. When the bucket is empty, further intents are rejected until it refills.


What does StaleIntent mean?

The intent timestamp is older than MaxIntentStaleness seconds. This usually indicates a very high-latency connection, a burst of queued intents being processed late, or a client clock discrepancy. Increase MaxIntentStaleness if legitimate players are hitting this on high-ping connections.


What is ReplicateState?

When true, the server sends a full animation state snapshot to all clients every SnapshotInterval seconds. Clients use this to detect and correct desync. When false, clients rely entirely on the intent stream for state tracking.


Can I use MotixNet without server authority?

Yes. Use Mode = Motix.MotixNet.Enums.NetworkMode.ClientAuthoritative for the default model where client intents are validated and relayed. Use ServerAuthority to block all client intents entirely. Use SharedAuthority when both client and server code may emit intents.


The owning client is not sending intents. Why?

Verify that IsOwningClient = true was passed to CreateController. Also verify that the animation names passed to Play are registered in the HashRegistry. Unregistered names produce a warning and no intent is sent.


Is it safe to call Controller:Play() from inside OnIntentAccepted?

Yes. OnIntentAccepted fires on the server's main thread. Calling Play or Stop on a server-side controller from that handler is safe.