Catbot (Locomotion)
Summary
Figuring out parts of a decently extensive locomotion included with slope locomotion and just trying to make moving around fun.
This is my most extensive locomotion system so far that I've developed.
Included are:
-multiple start/stop transitions
-direction leans both on ground and in the air
-locomotion on slopes
Character model is by Leo Varas: https://www.artstation.com/leosaurusrex
This is my most extensive locomotion system so far that I've developed.
Included are:
-multiple start/stop transitions
-direction leans both on ground and in the air
-locomotion on slopes
Character model is by Leo Varas: https://www.artstation.com/leosaurusrex
Video
Directional locomotion
The directional leans while moving are fairly standard in their implementation. I made runs in all directions and speeds and blend between them based on the rotational change of the player per frame with a blendspace.
Note: UE4 has a "Calculate Direction" node that will give you the direction between -180 and 180 degrees for you, which is based on velocity. The reason I used rotation instead of velocity is that using velocity tends to be jerky if it changes too quickly, such as if you hit a wall.
Note: UE4 has a "Calculate Direction" node that will give you the direction between -180 and 180 degrees for you, which is based on velocity. The reason I used rotation instead of velocity is that using velocity tends to be jerky if it changes too quickly, such as if you hit a wall.
A common setup for locomotion with directional shifts. Notice some subtle differences like a reduced tail motion on hard turns
I took this concept a step further and incorporated into the jumps as well - jump start, loop, and landing. By creating jumps for all directions and speeds, I could avoid foot sliding and make the character react to directional changes in the air, making a more fluid movement. I again used blendspaces to blend between the different directions/speeds.
The blendspace of the jump landing, with blends to account for a landing with no horizontal speed to a full sprint speed. Matching the final pose of the landing to its destination (idle, run, or sprint) ensures a fluid transition
Full sprinting jump. By making each jump match the speed of the ground locomotion, foot sliding can be avoided. It is ultimately exported in place
Additives
Additives were used for some aerial turns to save work. At first, I made unique fall animations for each direction but I found that by layering a pose on top of existing animations, it gave a comparable result with a lot less time, effort, and memory space.
The reason I did not use additives on the ground locomotion while on flat ground is because I wanted the animation to be more different than a simple pose change - while running to the left, the arm and tail motion is reduced, feet swing out more, etc. However, I did use additives on the slope running while turning to save time since I already proved out my concept.
The reason I did not use additives on the ground locomotion while on flat ground is because I wanted the animation to be more different than a simple pose change - while running to the left, the arm and tail motion is reduced, feet swing out more, etc. However, I did use additives on the slope running while turning to save time since I already proved out my concept.
Comparison of additive method for turns (left) to a unique animation per direction (right). I ended up using both since I didn't want to throw away previous work haha
Fun fact: the additive pose while running on a hill is the exact same additive used in the jumping shown above. A pretty good result for reusing assets!
All the catbot's animation assets for this project
Slope running
Math!
I found that to make a satisfactory slope run, I would need to know 3 numbers: the angle of the slope, which direction the character was moving relative to the slope (uphill, downhill, side), and the turning rate (which I already had since I needed it for turning while running on flat ground).
I won't go into too much detail, but basically I checked the normal of the floor the character was standing on first to determine if she was standing on a slope. If the character was standing on a slope (floor normal is not equal to [0,0,1]), then I calculated the rest:
Slope angle: arccosine of dot product of slope normal and world up vector.
Player direction relative to slope: First I got the cross product of the slope's normal and the world down vector (which could also be the up vector), which gave the right vector for the slope. Then I simply rotated that vector 90 degree downward around the normal axis, which gave the vector downhill. Taking the delta of the downhill vector and the player's vector gave the direction that the player was facing relative to the slope from -180 to 180, which told me whether the player was facing uphill, downhill, right, or left (and in between). In retrospect, I could have simply taken the delta of the slope normal and the player rotation to get the direction since the normal always points away from the hill, and I was only interested in the yaw rotation.
I won't go into too much detail, but basically I checked the normal of the floor the character was standing on first to determine if she was standing on a slope. If the character was standing on a slope (floor normal is not equal to [0,0,1]), then I calculated the rest:
Slope angle: arccosine of dot product of slope normal and world up vector.
Player direction relative to slope: First I got the cross product of the slope's normal and the world down vector (which could also be the up vector), which gave the right vector for the slope. Then I simply rotated that vector 90 degree downward around the normal axis, which gave the vector downhill. Taking the delta of the downhill vector and the player's vector gave the direction that the player was facing relative to the slope from -180 to 180, which told me whether the player was facing uphill, downhill, right, or left (and in between). In retrospect, I could have simply taken the delta of the slope normal and the player rotation to get the direction since the normal always points away from the hill, and I was only interested in the yaw rotation.
The nodes for the slope calculations
Since I don't actually know math well, I had to figure out the slope calculations theoretically and then find the appropriate math operations to achieve it lol
Whether to use the flat ground locomotion or slope locomotion is transitioned by a simple "onSlope" boolean derived from the above calculations. A Sync Group keeps the two different locomotions states in sync to maintain fluidity
When the character detects that it has hit a slope, it plays an additive "bump" which is scaled by the speed you hit the slope at. I added this because of a previous experience I had where I ran full speed into a slight slope and immediately fell down due the impact. I found that it helps make the transition feel more tangible
The slope run itself was a combination of two different blendspaces and an additive for the turning (as described in the additives section above). I made one blend space each for running and sprinting that each have the "Player direction relative to slope" and slope angle as their parameters, and blend between the running and sprinting blendspaces by velocity. This essentially acts like a blendspace with 3 parameters instead of just 2. The additive is layered on top to handle direction changes while moving.
The blendspace for sprinting on a hill. Horizontal parameter is whether the player is facing downhill, uphill, right/left hill, etc. Vertical parameter is the angle of the slope, which when it is 0, then the regular flat ground sprint plays
Blending the "running on slope" and "sprinting on slope" essentially makes a blendspace with 3 parameters instead of just 2.
Launching off ramps:
UE4's default behavior on ramps is to stick to it, causing a weird magnetism that's somewhat unsightly when you run over a sharp slope and also prevents running off of ramps. To get around this behavior, I added a check on every tick to determine if the player ran off a ramp. I won't get into the specifics of it because the implementation was extremely rough, but in essence it compares the directional and slope data to find the conditions for running off a ramp which are:
-If the player is running on flat ground and suddenly is running downhill
-If the player is running uphill and is suddenly running downhill
-If the player is running uphill and suddenly there is no ground beneath the player
Once an appropriate condition is fulfilled, then the player is launched into the air based on the velocity they were moving at and a unique "running off ramp" animation is played.
-If the player is running on flat ground and suddenly is running downhill
-If the player is running uphill and is suddenly running downhill
-If the player is running uphill and suddenly there is no ground beneath the player
Once an appropriate condition is fulfilled, then the player is launched into the air based on the velocity they were moving at and a unique "running off ramp" animation is played.
Default UE4 slope movement behavior comparison to my ramp launching method