Grappling Hook

Unreal Engine Tutorial

In a previous tutorial I talked about how to make a physics based grappling hook in Unity. This tutorial is a more in-depth look at how to do the same thing in Unreal Engine, with some more experiments and some comments on what parts were the same or different.

Introduction

There are two ways grappling hooks (or webs) typically work in games: 1) by pulling the player directly to the target, or 2) by swinging a falling player around the grappled point in a pendulum motion.

In this tutorial we will make the pendulum version of a grappling hook, so that players can swing around obstacles, and in the future I will add extra systems for retracting or accelerating.

Theory

Physics

Lets go over the physics of a grappling hook.

The main component of a grappling hook is the pendulum motion. A real pendulum has very simple forces acting on it: Gravity pulling it down, and the rope pulling it towards the pivot point.

The reason the pendulum swings back and forth is because the rope applies its force based on the position and velocity of the object. When the object first starts falling the rope applies a small force towards the middle while gravity accelerates it downwards. When the object is near the bottom the rope applies a medium force up, countering gravity but not effecting its sideways momentum. When the object has gone past the center it has a lot of velocity away from the pivot, so the rope pulls it up and back to the middle with a lot of force, causing it to curve upwards and towards the middle. Finally, when the object is mostly going up the rope doesn't apply much force to it, letting gravity decelerate it until it stops and the cycle starts again.

This means what we need to simulate from the rope is a force towards the pivot based on how much the object is moving away from it. The final implementation is quite simple, but this result came from testing a lot of different options and and fixing many different problems.

Maths

Saying that the force is based on the velocity is well and good, but how exactly do we turn that idea into the directions and values that we use to move the player? There are many different formulas used to calculate different parts of pendulum motion, but I want my system to be robust to things like collisions, strange gameplay forces or even changing gravity, so I don't want to use the ones that assume any part of the setup (like where gravity is coming from) or that calculate a position instead of the forces or velocity (as this would lead to clipping into objects).

The truly realistic way to calculate the forces is to determine how much the rope is being stretched at each point in time, and apply a spring force to 'restore' it. The main difficulty of this approach is stopping the player from bouncing and oscillating like they're on an elastic band - which can be made worse because of the large discrete steps of a physics engine.

Implementation

Attaching the Hook

Before we can calculate and apply forces to the player, we need a way for them to choose a point and attach the grappling hook to it.

First set up an InputAction for the button used to grapple:

Like most games we're going to get the grappling point based on where the player is aiming, and fail to grapple if there is nothing near enough. Just like in Unity we can draw a line from the camera and save the first point we hit as our target, which in Unreal Engine is called a Line Trace. This function only takes the start and end points of a line, and doesn't have options to take a direction and max distance directly like in Unity, so we'll have to use those values to calculate an end point instead. Here we run into another noticeable difference to Unity: the default unit is cm instead of meters, so my go-to big value of 100 doesn't even reach the ground from the camera!

Get a grapple point when pressing the grapple button:

Forces

Now that we've attached the hook, we need to actually apply the forces to the player. Before we do that we need change some of the settings on the player character to let it use more realistic physics.

Changes:

Now the broad strokes of the grappling hook system:

Most of these steps are simple, but using dot products to check if the player is moving towards or away is a little tricky if you've never used them before.

The dot product function is a simple but very useful maths function. For this situation we need to give the function normalized vectors (aka 'directions') - because when we do that the result is a number between 1 and -1 representing how similar the two directions are, with 1 being the same, -1 being opposites and 0 meaning they are at right angles.

This is how we check if the velocity is towards or away from the grapple point - by checking if the result of the dot product is greater than 0 or not.

Tension force

Now we just need to calculate the actual force the rope applies on the player. This is done by figuring out how much the rope has been extended past its maximum length, and applying that value with no changes as a force towards the grapple point!

Steps:

This gives a smooth and robust swing with a lot less effort than my unity version.

Old solution

In Unity the simple tension approach is a lot less intuitive, partly because the force units are different from the distance/velocity units - and this is why I came up with an implementation that used the players velocity to calculate the force to apply. This version works well, but is more complicated and has a small but noticeable problem - that the current solution was meant to be a band-aid solution for!

Velocity method:

Unfortunately this approach causes what I call 'gravity leak': While the player is hanging from something they slowly start drifting downwards. This happens because of the order of different parts of the physics calculations. First the code we wrote calculates the perfect tension forces to apply to the player. Then the physics engine applies gravity to the player, increasing their velocity by a tiny amount. Finally the physics engine moves the player using their velocity.

This means that the player always has one frame of gravity more velocity than they should, and slowly drifts towards the ground.

We could fix this by accounting for the gravity leak, but the maths is more complicated than you would expect, and it turns out there was a much simpler solution that I could have used from the start!