Content:

↑ Back to top

Advanced PhysX Based FPS Movement

Summary

In our 7th group project at TGA we were tasked with developing an FPS and my team and I settled on the Frontier Defense game mode in Titanfall 2 as our reference game. Our choice in reference game made me very excited since a large portion of the code from Titanfall 2 was ported over to make Apex Legends, one of my all time favorite online games. I have hundreds of hours in Apex and a large portion of those are from playing the character called Pathfinder, whose signature ability is functionally the same grappling hook that players have access to in Titanfall 2.

After some discussion about what each of us wanted to focus on in this project, my fellow programmers graciously allowed me to take on the task of single handedly developing the movement controller for our player character, including a grappling hook, momentum preserving ground slide, and more. Although the end result that I produced isn't a 1:1 recreation of the Titanfall movement, it's not all that far from it in my opinion. Given the scope of our project, the time frame I had to work with and sacrifices I had to make to have it better fit our game, I'm very happy with the result. I also feel that, with more time, I could continue working on the movement to make it even closer to Titanfall's movement.

The Grappling Hook

To emulate the slingshot moves that are possible in Titanfall, my grappling hook takes the current velocity into account as an additive factor to keep pulling the player slightly in the direction that they're already moving instead of straight toward the grapple point.

Spring Dampening

A completely stiff grappling line wouldn't feel very rope-like, so I added some springiness to my grappling hook to make it feel like a rope tugging at you, instead of just a force of gravity pulling you in.

In a similar vein to the additive velocity factor when calculating direction, this part of the force calculation exists to help the slingshot functionality emerge. It does so by calculating your tangential velocity (the speed of an object undergoing circular motion) along the pull direction, basically to make it pull you in less when you aren't already moving in the same direction that it's trying to pull you in.

Fighting the Pull Force

To give the player further control of how the swing of the grappling hook ends up I also allow a small amount of directional movement during the grapple, added onto the rest of the calculation results into the PhysX body.

Snapping Conditions

Finally I have two main conditions deciding whether to automatically end the grappling, "snapping the line" so to say. One is the player being close to the grappling point, either from having been pulled there over time or by grappling somewhere right next to themselves. The other is that the player has a large velocity away from the grapple point after the grapple forces have already been applied for three fourths of a second, at that point we can assume they are doing a slingshot maneuver of some kind.

Go to the function on GitHub

The Rest of the Movement

Input Mapping

To accommodate both mouse and keyboard as well as gamepads to play our game I leveraged the Command design pattern, encapsulating what triggers certain actions to be controlled by a separate interface from the player controller itself. This also meant that I had to make the movement equal between input given by an omnidirectional joystick and the more limited combinations of cardinal directional inputs possible using the WASD keys.

Grounded Check

The grounded check is a simple raycast in the PhysX Scene, casting only against the collision filter/layer of environment objects. If there is a collider on the environment layer right under the player's feet at their center of mass, they count as grounded and I store the normal of the intersected object at the ray's hit point for use in later calculations.

Go to the function on GitHub
Grounded Movement

The movement on the ground is calculated as a speed scalar multiplied by the directional input from the Input Mapper, using a different scalar based on if the player is sprinting or walking.

Go to the function on GitHub
Ground Slide Boost

At the start of a ground slide I apply a small boost to give the player some extra momentum and to incentivize using all the movement mechanics at their disposal over and over.

Go to the function on GitHub
Custom Friction

The custom friction was both a solution necessary for the scope of our project and a key component of the ground slide mechanic. The scope of our project simply didn't allow for any time allocated to going around configuring various specialized physics materials to use on surfaces in our level to fit the player controller. It was much easier for our scope to just remove friction from all environment objects and delegate that responsibility to the player controller. When ground sliding, the custom friction preserves most of the current momentum dependent on the surface normal of the object under the player's feet. When walking or sprinting, the custom friction instead acts as a catch-all "slow down slightly after the player lets go of their movement input" surface material, along with some extra force to counteract sliding on slopes. In a larger scope, all these components could be adapted to be different based on the name/tag of the PhysX body that was hit by the IsGrounded raycast.

Go to the function on GitHub
Mid-Air Control

The player is allowed a small amount of directional input control while airborne, fighting against their current velocity to try to change the direction they're headed. Our level designers asked me to give the player more "surf" capability like in counter strike games, so the if statement (at the end of the function) checking against the dot product of steep slopes under the player's feet allows for a little bit of extra air control to allow more of a surf-like behavior.

Go to the function on GitHub

To enable slingshot jumps like those possible when hooking the ground with the Titanfall grappling hook, I simply check if the player is grounded while grappling and launch them at a great velocity upwards along the Y-axis whilst preserving their velocity along the other axes.

Go to the function on GitHub
Double Jump

Just like in Titanfall, our game has a double jump, and my double jump feels very similar to theirs in my opinion, fighting against any current downwards velocity to act more like an air jet shooting down to lift you rather than just kinematic movement (movement without regard for current forces acting on an object in motion) pushing you upwards.

Go to the function on GitHub

Highlight Reels

Traversing between defense points using the grappling hook
Various slingshot jump moves
Using slingshot momentum to parkour
Ground hook slingshot into b-hop
Swing force slingshot
Smooth swing-up to scale elevation