Holy shit I underestemated the amount of work I needed to do in order to allow you to swing with both hands. Using multiple ropes at the same time that is. I probably fucked up most of my swinging code, but god damn, it works. I'll rewrite most of the code later anyway. Not because of the performance, but because it looks like a clusterfuck. Plus it will make it easier to update at a later point anyway.
Oh, and by the way, I've also been working on some parqour mechanics. You can now run along walls, do walljumps, etc. I'll work on it more tomorrow, because I really need sleep now.
When I was younger, I remember that I absolutely loved to play Spiderman 2. Not because of the story or the fighting, but because of the great web-swinging mechanics created by Jamie Fristrom. He has since successfully launched and funded a Kickstarter for his new game "Energy Hook". While I'm looking forward to this game, I can't help but feel like there's some missing potential here. I do realize that I'm using is old footage, but it issue still persists in the latest footage, although it's better illustrated in the Alpha footage. I'll talk about this in a bit. Here's vaguely how I implemented swinging using a rigidbody player controller. Keep in mind that this is not a tutorial, but rather a little pointer towards challenges you might meet.
Issues and solutions.
After configuring the Configurable Joint to behave as a rope, we needed to connect it to something. So we're doing a raycast on Fire1 and instantiating a rigidbody anchor there. We're calling this position "AnchorPos". We want to do a raycast from AnchorPos later on, and that raycast is going to go through the wall if the raycast hitpoint is exactly at the edge of the object. So in order to prevent our anchor to go inside the wall, we're just making it have a very large drag, making it stand still while also making it not enter the wall. When the anchor is finished going out of the wall and is not moving anymore, we're making it kinematic to save our performace a bit. We're then doing a linerenderer between the anchor and our player.
Now we just set the connected body to our anchor and we're hooked. The issue now is that we'll either fly towards the anchor or nothing will happen until we move away. This is fixed by setting the Linear Limit, or in our case, the rope length, to the distance between our player and the anchor. We now have a rope that we actually can swing with! We also need to set ConnectedAnchorPosition to the Anchor position on our local matrix.
We also want to disconnect from the rope though. Apparently setting the connected body to none will result in our player standing still midair. I also encountered an issue that would cause the player to receive enough force to go through the ground or into space when the connected body was removed. So I simply set the rope length to infinity when we want to disconnect the rope. We're no longer breaking the laws of physics. Well, we kind of are, but nobody's going to notice.
What we've got now is pretty much the core of our swinging. We could stop there, but it doesn't really feel right, plus our rope is going through walls! This is also an issue in Energy Hook
This footage clearly shows the rope going through the sign, which is fine, since it's not actually a rope, but rather a line of energy (According to the developer).
I think this is cheap and wrong. So let's fix that.
In order to achive the rope bending, here's what we need to do:
Pretty simple stuff.
We will now be able to bend the rope around corners! We're now attached to the corner instead of the last anchor position. This also means that our rope-distance is wrong. To fix that we simply do RopeDistance = lastRopeDistance - distanceFromAnchorToCorner.
Now there's a new issue.
So the initial rope length was 10 meters. Since I've allowed the rope to be stretched a bit to create a slingshot effect when you're grounded, it means that while the rope tries to be 10 meters, it can be stretched like a rubber band. The actual rope-length value stays the same. In the example above, when the rope hits a corner, it would become -0.1 meters long, which is impossible! This is causing the joint to constantly correct the player, making him either launch into space or teleport all over. Neither of these options is something we want, so we simply don't decrease the rope length if it's going to get bellow a certain value. This is also causing the rope to actually become a bit longer when it should become 0 or less, but it doesn't matter. You can't really do anything with a rope that short anyway.
An important part that you'll probably notice if you use this method, is that the anchor gameobject will be instantiated somewhat inside the wall. We could do some hocus pocus to fix this, but in order to make sure it always works, we simply make it a rigidbody with very, very high drag. The anchor will pop out of the building and we can move on to our next challenge. I know I've forgotten something at this point. I guess you'll find out what it was when you create your own.
Alright, so this is the "fun" part.
Unlike Power Hook, I don't want to do jetpacks or anything like that. But I quickly noticed that we weren't really gaining any momentum when swinging, and what we gained was very low. If you look at the Spiderman web physics, you will notice that the rope is more like a rubber-band. The web is somewhat shrinking in length, so let's try mimic that and see what happens.
If we reduce the rope-length by a little bit when we hold space, we achieve a YoYo-effect(?), which means that we'll gain momentum if we time it right! But it feels really wrong to have the rope shring gradually by x amount when we hold a button. So by scaling the shrink-size based on the rope-length with about 1%, we achieved a reliable and predictable shrinking size, making it easy to get around corners and gain momentum. Awesome!
I can't really remember much more at this point, so I'll just leave you with this nice video of me swinging around with way too much speed.