Root motion movement
Unity 3D -- C#
▚ Project summary:
For this project, I am implementing a high quality root motion based movement system.
In this project, I want to apply all the things I learned on root motion, animation scripting, movement systems and more during my previous projects and school assessments.
Aiming to have correct animation driven movement would help me get closer to the quality I want to achieve within my own, and shared projects.
I also want to be able to use this project as a base for my next projects, where the movement itself will always feel up to the quality I try to reach in my personal projects.
Page contents:
·Desired rotation calculation
·Start and Stop movement
·In place Idle turning
·Walking, Running and Sprinting
·Jumping, Falling and Landing
▌Specifications:
Released: April 2022
Project type: Personal project
Platform: PC, Windows
Time spent on project: 1 month (not full time)
Engine and Tools: Unity 3D - C#
▌My contributions:
○ Fully working root motion based movement system
○ Desired direction calculation using input, camera rotation and player rotation
○ Start/stop root motion implementation
○ Walk/Run/Sprint implementation
○ In place turning implementation
○ Dynamic jump implementation
○ Falling implementation
○ Landing animation implementation
▌Project goals:
○ Create a fully fledged out, AAA quality root motion movement system.
○ Create a core movement system to be used as a base for my other (personal) projects.
○ Apply the research I did on desired direction variable usage.
○ Realize the root motion system inside Unity, using C#. Experimenting was done using blueprinting in Unreal.
▚ Work in progress
This page is currently a work in progress, any development updates and explanation on how I achieved certain features will be added as soon as possible.
▚ Desired rotation calculation
When the player starts moving, specific start and stop animations have to be played. The animations that I support, range from a 45, 90, 135 and 180 degrees start animations. To know specifically which animation has to be played, a calculation has to be done before moving, to determine the “desired” movement rotation.
The calculation uses the active player rotation, camera view direction and active input to determine the desired rotation. The code is still a work in progress, but the main calculation is shown below:
In unity, rotation degrees range from values that are higher than +180 or -180, so I created a custom wrap function to wrap the rotation value. This helped with directly using the calculated value in the animation controller.
With the animations disabled, the calculated desired rotation value is visible in the debug window.
This desired rotation is the core of the start and in place rotation functionality, an important element of creating a high quality root motion movement system.
▚ Start and Stop movement
The start animations are triggered when the player speed increases from 0. When you want the player to move directly towards a desired direction, having multiple start/ start-turn animations makes sure these turns towards the desired direction look and feel of high quality.
After doing the calculations shown above, The desired rotation value is set every frame in the animation controller.
As you can see in the image below, there are many states in my animation controller. The more features I add, the more complicated the animation controller becomes.
When in idle state, I check for the set player speed. If this speed is higher then 0.01. I transition to the start animation blend tree state.
In here, as you can see on the right, the desired direction value is directly used to play they right root motion start turning animation.
This makes sure to play the right start turn, which is followed by the desired speed forward movement.
The result of the starts can be seen below
The start blend tree:
▚ In place Idle turning
A really clean looking feature I wanted to implement is in place idle turning. This means that when the character is idling, and a the desired rotation value is reached, in place turning is activated to match the desired rotation.
In the code, I check if the desired rotation reaches a absolute value that is higher then 90 degrees.
If this happens I trigger the TurnInPlace boolean. When the animator controller is in the Idle state, the active turn direction is used to determine to either turn left, or right.
The result is really clean rotational movement during idle behavior, which adds to the desired quality of my root motion movement system.
In place idle turning, with the conditions listed:
▚ Walking, Running and Sprinting
The main forward movement, is the important state after the start state. The desired movement speed is calculated by adding the x input value (clamped), together with the y input value (clamped).
When entering the WalkRunSprint (forward) state, this speed parameter is used to smoothly blend towards the desired speed forward movement animation.
Making sure the blending is balanced and properly working, while switching movement speeds, is important to correctly switch from walking to running or switching to sprinting when necessary.
Although running and sprinting are set as the main 2 movement speeds in my project, walking could still be dynamically enabled when E.G walking on a steep hill.
The walking/running/sprinting blend tree:
▚ Jumping, Falling and Landing
Jumping and falling is important to get right. Instead movement through static jumping animations, I learned it's better to separate the jump starting, falling and landing. This way, the landing logic can be applied, even when the character suddenly is not grounded anymore.
Using the new unity input system I first check if the player is pressing the key to start jumping.
Besides the player grounded check, the rest of the jumping logic is handled by the animation controller.
Is grounded check:
Besides checking for collision with the ground, I also check the distance from the feet and from the middle position of the root.
If this distance from the ground is lower then a specified value, it means we are grounded. This helped with having a consistent grounded value, even with special use cases like slopes and stairs.
The Start Jump:
When the jump is triggered and the player is grounded, the Jump start state is played. This uses the active player speed to play the right jump animation for the right active speed.
If the player is still falling after the start jump animation has finished, it transitions to a looping falling animation.
Landing:
I start the landing animation when several conditions are reached. I learned landing animations work better when the player is already touching the ground (grounded), instead of trying to start a animation on time, when falling.
I also make sure to wait with triggering the landing animation, until at least the highest point of the jump has been reached.
The jump start blend tree:
The landing blend tree: