I spent 7 weeks recreating a game feature that I love, the grappling hook from the Just Cause Series. I chose to work in Unreal Engine so that I could be totally focused on the gameplay feeling.
I set out to recreate a gameplay feature that I really love and fully immerse myself in what makes it so enjoyable and how I can recreate that. I chose the grappling hook from the Just Cause series, more specifically the part of it used for moving around. Doing this in Unreal Engine 4 has taught me how to use the engine and script using blueprint. I prefer writing code, but by using Unreal’s Blueprint system I now have a better understanding of how scripters work and what features they are accustomed to. Which I can use to better work with them in the future. If this was a longer project and I had more time, I would have moved the logic into C++ and expose values and events into blueprint.
My scope was to create the core of the grappling hook, hooking on to a surface and launching the character to that position. I decided to support hooking on ground, walls and ceilings. There are different ways the character reacts to the grappled surface. If it’s the ground or another surface the character can stand on, the hook disconnects when the character has reached the destination. If it’s a wall, then the character remains hooked to the wall and stands against it. If the target position on the wall is low enough that the character can stand next to it, the hook is released and the characters stands on the ground instead. If the hook target is in the ceiling the character will not release the hook and stand upside down on the ceiling.
Hooking to a ground surface
Hooking to a rotated surface
Hooking to a wall
Hooking to a ceiling
Here are some videos from earlier version of the project.
Implementing the wire
Rotating correctly to the hooked surface
Hooking to a rotated surface
Problems during development
Here follow some problems I encountered during the development, my thoughts about them and how I solved them.
Camera clipping into walls
I built my character based from the standard third-person controller template in Unreal Engine. The camera has a spring arm component that by default works really well with not clipping into walls. But since I wanted the camera to be more over the shoulder and to the side, the wall avoidance did not work so well anymore. At first, I offset the camera by just moving the camera position to the side, but I later realized that the spring arm component has an offset variable that I started using instead. This solution worked really well, in most cases. The offset is in world space, which caused the camera to clip into walls on one world axis. This was because the position the camera looked at would be inside the wall.
I tried using a local offset instead but it gave weird snapping results when rotating the character. I think the standard third-person controller is designed in a way that makes a local offset weird. I decided that it was more important that moving around felt nice than the camera clipping into some walls, so I kept the offset in world space.
After giving it some thought I implemented a fix. Whenever I hook and stick to a surface, I calculate a new camera offset using the surface’s normal. This ensures that the offset will not be in the wall I grappling hook to. There would still be a problem with close walls if the offset would place the camera inside one of them. I worked around this by designing more open levels and trying not to have walls too close together. I also added some interpolation to make the change of offset a little bit smoother.
Character stopped by collision while flying to the target
Another problem I faced was when the character would be unable to move towards the grappling hook target because there would be an object in the way. For example, if the player would shoot the grapple hook while in the air and then fall behind something before the hook could reach the target.
I played around with some different solutions, the first one was doing collider sweeps to the target while flying there. If a collision other than the target object would be found, the grappling hook target would change to the collided object. This solved the falling example, but I found that in most cases it stopped you even when you thought you would be able to move past it. I tried changing the size of the collider but the result wasn’t improved by much. I decided that it was taking away more from the experience than what it gave, so I continued my search for possible solutions.
My next and final solution for this problem was to turn off player collision while moving to the grappled target. Through playtesting, I realized that in most cases the player did not notice the character clipping into objects because they were moving so fast. When they did notice, they were more forgiving than when they did not go where they wanted to go because there was a small object in the way.
In Just Cause, the target changes if there’s something between the character and the target. If I would have had more time, I would have continued iterating on the collision sweep solution to keep the character from clipping while still not punishing the player.
The character noticeably clips into the ground when flying towards the target
This appeared as a side effect from the above problem’s solution of turning off collision when moving to the target. Because of the reasons I chose to turn off collision, I thought it was worth trying to find a workaround for this problem instead of turning collision back on. I chose a pretty simple solution, offset the target position in the up axis to fit the size of the character. The character would move towards a position above the ground instead of on the ground, therefore avoiding clipping into the ground. I only did this when the target was a ground surface because I didn’t have this problem on the other surfaces.
Making the character nicely react to every surface
The final problem that I want to talk about is the biggest challenge of this project, grappling hooking to different surfaces. With different surfaces, I mean for example flat surfaces, curved surfaces, upside down surfaces and more. For every surface, the character would need a specific animation and offset position to sit nicely at the hooked position. Because of this being a short project, I decided to set the scope at handling 3 surfaces: ground, walls, and ceilings.
It took a lot of time making the reactions look nice with animations, blending and smoothly moving the character into place. I handled a lot of specific cases, like for example when hooking to a position on a wall that’s close enough to the ground for the character to stand, I released the grappling hook and made the character stand instead of hanging on the wall.
I rotate the character to face the surface’s normal, which made curved surfaces look okay even though I didn’t intend on handling them. I decided to put a sphere in the game that the player can hook onto, even though it doesn’t work perfectly all the time.