How do Roblox animations work?

Hi,
I am making a roblox animation plugin.

I’m trying to understand how Roblox animations work beyond just creating and playing them in Studio.

Could someone explain:

  • How Keyframes / KeyframeSequences are processed when an animation plays
  • How animations affect Motor6Ds, and why they don’t seem to affect Welds
  • How the Animator / AnimationTrack system applies pose data to a rig

I already know how to make and play animations, but I want a clearer understanding of what’s happening behind the scenes.

I did read the roblox docs but didnt understand anything.

Thanks!

1 Like

I’m not too entirely sure myself, but If I had to take a quick guess, I’d say that keyframes operate by setting CFrames in the affected joints, limbs, and body parts. Animations probably just set the transform data of an Motor6D. Animators just start the Animation Track which is a sequence of the Keyframes. Roblox probably uses a stopwatch system where the passed for the animation increases by the servers deltaTime. Then when the stopwatch threshold has passed the threshold for the keyframes, it applies the CFrame transformation to the Motor6D. But you also how to consider easing styles.

1 Like

When you make an animation in Studio (or import it), you get a Keyframe instance for each unique time on the timeline of the animation where there is a animation data for at least one joint. All the Keyframe instance does is group all the Pose children under it, associating them to that point on the timeline.

Each Pose instance is just wrapper for a CFrame, a CFrame which is applied to the joint it corresponds to. For R15 Motor6D animations, the Poses are named the same as the body part MeshParts, e.g. Right UpperArm, but the Motor6D they affect is the one parented to that part, in this case RightShoulder. The Pose.CFrame data is applied to Motor6D.Transform. When the character is at rest (standing in the platform pose or “I-Pose”, all of these Transforms are just CFrame.identity, i.e. no rotation added.

When the animation plays, the CFrame that ends up as the Motor6D.Transform is usually a blend of the two nearest available Pose.CFrames on the timeline for that joint. This is because the animation track TimePosition (the position of the virtual playback head along the timeline) doesn’t jump from Keyframe to Keyframe, it’s a continuous float value, so it can be a time between two Keyframes. For each joint, the Poses from the keyframes before and after the current TimePosition are interpolated between. The interpolation is linear by default, but there are other easing curves you can select. Using “Constant” effectively removes interpolation, and just uses the last Keyframe at or before the current TimePosition.

Welds don’t have a Transform property, so they can’t be animated. Roblox animations can only play directly onto 3 types of animated joint: Motor6D, AnimationConstraint, and Bone. Bones are animated the same way, but the actual rendering happens on the GPU, as they are not physics engine simulated joints like the other 2.

The Animator in your character can have a bunch of animations playing, each with its own AnimationTrack and timeline, and it blends them together based on the weights and priority of the playing tracks. All the playing tracks are evalulated, joint by joint, with the Pose interpolation mentioned above, and they they are blended together joint by joint, based on the track weight values and taking into account track priority (tracks with full 1.0 weight and higher priority will fully override tracks with lower priority). The blending is a normalized weighted blend, it’s not additive, i.e. you can’t play 2 animations at weight 1.0 with the same priority and have the full transforms of both combined, you’ll get a 50/50 mix of the two.

1 Like