RootMotion module | Animate the HumanoidRootPart with ease! | Simple | No conversion needed

Root motion

View the GitHub repository here
Get the source code here
Insert the ROBLOX model here

This module allows you to easily achieve root motion in your game with no extra steps required. This saves you the work of configuring forces or cframes in your script constantly to achieve your desired effect you want on the player’s torso. Now, you can animate the torso in any animation tool you want, and this module will do the rest of the work! Unlike other solutions, this doesn’t need require you to convert every single animation in your game to fit the format. This module will work out of the box on any animation which animates the torso. No extra work is needed from your end!

Features

  • Strictly typed - This means this utilises LUAU’s type solver to spot mistakes in your code inside the linter. This saves you time fixing bugs because you forgot something.
  • Performant - This module leaves a very low memory footprint inside the game, and the calculations take up very little CPU time
  • Out of the box - You don’t need to completely reimagine how your animations work in order to utilise this. All you have to do is animate and let the module do the rest of the work.
  • Simple API - This module only provides two self-explanatory functions for you to use.

Drawbacks

  • Primitive physics - This doesn’t rely on ROBLOX’s physics to apply it’s physics. While this means you can’t get flung by any external parts, it also means you may not be able to experience pushbacks if you want to.

FAQ:

Why should I use root motion?

Root motion allows you to animate the HumanoidRootPart (HRP) of rigs. This is important if you rely on the HRP for hitboxes or you don’t want the animation to fade back to it’s original position after it ends. Below is a clip of a simple animation (don’t mind my bad animations) being played with and without root motion. The difference is night and day;

What rigs does this module work on?

This currently works on both R6 and R15 rigs. If you use a custom rig then you will need to adjust some parts of the module to account for this.

What are alternatives to this module?

You could always strip the torso keyframes out of your animation and then manually position it using CFrames. However this is tedious. Another solution is to use bodymovers to move your rig around. This is easier to do but can be hard to perfect for small details you’d like to implement.

I have an issue or suggestion!

You can either comment under this DevForum post with your problem, or open up an issue on the GitHub repository (linked above). If you’d like to contribute then feel free to open a Pull Request on the GitHub!

This module is probably the best alternative to this module, however it’s API is much more complex. Moreover, extra work is needed to convert your animation to an acceptable format for the module to work. This module doesn’t need any extra work from your end to achieve root motion.

API

type Configuration = {
    ["Whitelist"] : {Part | BasePart}?,
    ["AlignHRPCFrame"] : boolean?,
    ["MaintainVelocity"] : boolean?
} --// If left nil, the booleans will be assumed to be false

:StartCorrection(Configuration : Configuration)

Starts correcting the character’s HRP cframe to keep it in line with the torso’s animation.

  • Whitelist - allows you to add extra parts / models for the collision detection to ignore. Your character will noclip these parts when being animated instead of stopping in place if it comes into contact. Parts with no collision are automatically ignored.

  • AlignHRPCFrame - Aligns the HRP with the player’s horizontal look vector. This is useful if you want all your animations to start at the same level, regardless of the player’s prior orientation or not. For example, if you play an animation with this setting off and the character looking at the floor, then they’ll be lower than if they were standing. This setting allows you to avoid these situations.

  • MaintainVelocity - This maintains the character’s velocity after the root motion ends. Normally after root motion, the character will just freeze up if you want to ragdoll them afterwards since ROBLOX doesn’t automatically update their velocity. This updates the velocity for ROBLOX so the character’s motion is maintained and any after effects look natural.

RootMotionModule:DestroyDependencies(ReverseAllEffects : boolean, Replicate : boolean) 

Stops the HRP from correcting it’s CFrame in line with any animations

  • ReverseAllEffects - Reverses all effects the module applied to the character’s physics and makes the character automatically stand up as if nothing happened.
    If left false, the character will stay in the:
    – Physics state
    – No autorotate
    – Camera subject is the head
    – All limbs have no collision

  • Replicate - Enables or disables replicating this to other clients. Read the bottom of the post if you want to implement proper replication for this module.

RootMotionModule:MaintainTransform(Enabled : boolean, Replicate : boolean) 

Continues correcting the transform property even after the module has stopped, but doesn’t correct the HRP’s CFrame. This is useful if your animation fades out, but you don’t want to move the HRP back.

  • Enabled - Either starts or stops the correction
  • Replicate - Enables or disables replicating this to other clients. Read the bottom of the post if you want to implement proper replication for this module.

Replication

You may notice at the bottom of the module, there is code relating to remote events. If you’d like to prevent other characters overshooting their cframe’s, then you need to insert the code in a script. At the top of the module, there is also an event parameter which is commented out. Once you’ve inserted the code at the bottom of the module, you can add a remoteevent and uncomment that line. Throughout the module there are parts which are also commented out which fire that event. You should also uncomment those lines in order for this to work.

53 Likes

Helloooooo

So I just discovered a bug based off the replication of the root motion due to my oversight. Basically on other clients, since the animation is playing with the torso rotating, the other clients will already see the animation moving. However, what this module relies on to stop the animation from overflowing after setting the HRP’s CFrame is the setting of the RootJoint’s .Transform to the identity CFrame. This eliminates all torso offsets and matches it with the HRP’s CFrame so the animation doesn’t overflow. Of course, .Transform property doesn’t automatically replicate. This means that while the torso gets animated on other clients, so does the HRP. This leads to a pretty annoying visual bug where it looks like the character rotates more than they should or move further.

The fix is to just fire a remote event whenever the rootmotion begins and when it’s received (on other clients), just start a presimulation event which sets the character’s rootjoint’s transform to the identity cframe. Then when the rootmotion ends, send a signal to end the transform and simply disconnect the event.

Sorry for the inconvenience!

4 Likes

I hate to bump this thread but I just experienced another bug which you should probably be aware about:

Basically, stopping the rootmotion module from applying after AnimationTrack.Stopped:Wait() will cause the humanoidrootpart to snap back to it’s original pose (or roughly around it). This is because unfortunately currently you cannot overwrite the AnimationTrack’s fadeback speed after it has already stopped. This leads to roblox’s animator overwriting the .Transform property of the RootJoint Motor6D as if it was playing as normal before fading back to the identity CFrame.

There are two ways to go around this:

  1. Instead of relying on AnimationTrack.Stopped, just wait the length of the track and multiply it so it passes just before roblox automatically stops it
task.wait(AnimationTrack.Length * 0.95)
  1. After stopping the module, add a new connection for a temporary amount of time at PreSimulation simply setting the RootJoint’s .Transform property back to the identity CFrame.

In the meanwhile, you can like this bug report so engineers will hopefully notice it and rectify the issue.

2 Likes

I need help with the distance you move in the animation, it is not exactly the same in game; my animation has the player vaulting quite a considerable distance but in game they only move 1/4th the distance

Hi!

Interestingly enough when I started out with developing this module, I thought I experienced the same issue. However, after playing the animation normally and with rootmotion side by side, I realised that it still covered the same distance.

If you insert your rig onto the floor and then animate it through a plugin, you’ll realise that the distance travelled isn’t as large as you thought it was.

TLDR: The distance you think you made the animation travel is likely an illusion and is probably much shorter than you think.

If you’re sure it isn’t an illusion though, just send a clip showing a normal animated rig and a rootmotion animated rig side by side, and I’ll try and fix the issue.

2 Likes

Were you able to get the module to work on R15?

I haven’t tried adding support to it yet simply because unfortunately I don’t have the time to do so and test it, especially since all my workflow is on R6 rigs.

However, I don’t imagine that it would be hard at all to do in theory. Simply replace the ‘RootJoint’ with the path of the R15 rig’s root motor6D and correct the LowerTorso’s CFrame every frame instead of the Torso’s CFrame.

V1.1:

  • Added R15 support
  • Added ‘MaintainTransform’ function
  • Added code for implementing smooth rootmotion for all clients at the bottom of the script (you will have to manually insert it)
  • Uploaded onto the creator store
  • ‘AlignHRPCFrame’ no longer snaps the character towards the camera direction

The ‘MaintainTransform’ function allows you to keep the HRP at the same position it was at when the animation starts to fade out.

3 Likes

now all you have to do is add into consideration outside velocity, by this i mean if the player has a bodyvelocity then include it into the movement calculation, so you could use this thing on boats for example

Hmmm, I might do that later on, I’m currently focusing on exams.

Funnily enough I’ve implemented something similar in my personal version of this module catered for my own game, however the force is entirely through code rather than me reading off a force under the player’s HRP.

hi! could this be possible for this module to run on the server? as in i use it on the server?

there is another issue currently, i dont know if you fixed it or not, but the thing is, that the system causes the animation to snap, so when the animation ends if i use task.wait(track.lenght) it snaps back,

so it causes it not to be smooth.

You could fork it and it could work on the server. However this would probably only work for server owned rigs like NPCs and look acceptable. I suspect that trying to apply this on the server on client owned characters wouldn’t look great.

You can use the ‘MaintainTransform’ function to fix this. That was the exact reason why that function exists.

maintain transform just makes the torso stay at the same height as it was in the animation, causing it to mix up with diffrent animations and making it look un-natural, i tried using the module on client(as intended) and i still get those “chopped” moments

Could you clip the ‘chopped moment’ youre talking about and send it here please.

1 Like

Can you provide an example of how to use this? There doesn’t seem to be any documentation on how to get started or use this (apologies if I have missed it).

1 Like

It’s in the forum post..

Just scroll a bit inside the original topic message

1 Like


Hello! This is my first time using a module created by another person and I’m not sure what to do. I’m lost :sweat_smile::sweat_smile:

1 Like