First of all I need to give credits to this guy. Man not only made a video walkthrough, but also two pages of reddit post, step by step, with images, to teach us how to make a cool grappling hook mechanic in unreal engine. Links below:
https://www.youtube.com/watch?v=s3KUmwc7zwQ&t=186s
https://www.reddit.com/r/unrealengine/comments/empxb3/grapplinghook_text_tutorial/
Most of my changes are on BP_FirstPersonCharacter. For basics, I added a ball in front of our character, and a cable.
The ball functions as an "anchor" for the grapple hook. And the cable is to act as the "body" of the hook.
Absolutely loving this beefed up looking camera dude btw.
For now I have kept a lot of nodes that come from the template (which I will trim down later), but here's the bread-and-butter: grapple action. (Nevermind the small graph, I will go into details on them)
========================================================
Note: All functions will be Bold, and all parameters will be Underlined,
========================================================
I first setup the keybind action of grapple in Project Settings.
I have grapple hook's grab/release on RightMouseButton's push/release
Above is the first part of my GrappleControl function.
It starts off with InputAction of Grapple, which is triggered by holding down Right-click.
When the key is pressed, action triggers, it calls the SphereTraceByChannel function, this function takes Start and End to create a trail/trace in between and that is to simulate the trajectory of our hook-shot.
The Start is defined by World Location of our hook anchor (that small sphere)
The End is defined by where the player's camera is facing/aiming (that vector that defines direction), multiplied with a pre-defined Hook Distance
Below is a demonstration of how SphereTraceByChannel functions. Red lines shows where the "trail" is projected from, until it registers as a "hit" on the wall where it turns green. We can understand this function as a "beam" that the player shoots out from its hand.
Above is the 2/3 of this function, extending from the SphereTraceByChannel function, as we will be utilizing two of its outputs: Out Hit, Return Value.
We can consider SphereTraceByChannel as a beam here.
Return Value goes into a Branch that validifies if SphereTraceByChannel captures anything on its path, in other words, other logics only run after we're certain that the beam "hits" something.
This "something" is represented by Out Hit, is then thrown into BreakHitResult, a function that processes the "hit" result of SphereTraceByChannel
We need two things from this hit result: Impact Point, Hit Actor
Hit Actor is the actor that the SphereTraceByChannel beam lands a hit on, in other words this is the object that we landed the grapple onto.
A "hit-hit" is only validified when the Hit Actor has a tag (check through ActorHasTag) called "Hookable"
Hook Point is there the "hit" registers, in this case where the other-end of this grappling hook -> where we will be swing from, the centroid
Result of BreakHitResult then get passed to another Branch and a grapple shot is only valid when the player lands a hit on any Actor/scene-object with the tag "Hookable". Now that we can confirm a hook-hit, we need to start simulating what happens after the player lands a hook.
SET here is a setter that updates the variable HookPoint, which is a 3vector that collects a (x,y,z) location, with this step we register the location of a hook-shot
SET here is a setter that updates the variable GrappleConnected, which is a Boolean that registers the status of a hook shot, True for "hit", False for the otherwise.
Now that we can register a grapple-shot hit on our assigned object/Actor, what's next? For sure, we need to make the visuals available to the player: the cable and grapple
Under normal circumstances, aka Default, the cable is invisible . This function un-toggles the invisibility, reveals the cable when it is hooked onto something.
Now that the cable is visible, we need to transform it according to the state of the grappling hook, meaning that we will connect this cable from where our hand is, to where the grapple landed on: the Hook Point, and during the transformation, only the scale of this cable will be changing (actually I will experiment with rotation once other things are functioning).
The final step here is to spawn the grapple actor (that we defined somewhere else, see below) onto the Hook Point signaling that the hook "landed".
The idea here is that we can try to put things together piece by piece to create the illusion of their "unity" through other methods... for example using textures
This is the grapple actor, its hitbox has a child node that is the glowing mesh we see encased inside the sphere hitbox (hit-sphere).
Now that the player can shoot grapples around, we also needs the grapple to disconnect and disappear when the player releases right mouse button. Here is how I do it.
Still using the same InputAction Grapple (yeah I just moved it), and we now want to give the player a bonus speed when he/she comes out of the grappled effect.
This might be updated later for different gameplay experience, but for now, it simulates a physics scenario that
"when you let go of the rope when you're spinning around grabbing it, causing you to fly out towards a direction", kind of like this image on the left:
As our player is flying out, we want to simulate that the grapple is retrieved from the end, (unless I want to add grapple marks later on but for now it is not needed), so we call DestroyActor (we know which Actor it is by returning it from SpawnActor HookPoint) here to remove the grapple, and since the cable is a part of our character, but not something that the player spawns, it just needs to be set Hidden again.
Here is a set of math formulas to calculate how the player can move around the grapple point, swinging around on the cable. All the calculations get counted into a force that applies to the player's movement. Kind of like this guy ->
Then on top of the applied force, I want the player to have a little more control over the swing. Therefore as the player is flying around on the cable, I will give him/her a little nudge towards where the camera is facing.
Finally, just to improve the player's experience re-hooking to another target mid-flight, I added this function that increases the hook length/range based on the player's current movement speed: from default 2000 and scales up infinitely!!! (lol this might cause me more trouble later but I'm keeping it as long as it won't break). Similar logic could later be used for calculating player's damage numbers.