This website and this project was created by me in 100 hours over 5 weeks
During our latest project I spent most of my time working on engine related implementations. Because of this I wanted to do something more visual and gameplay related for my personal project. I wanted to get a feel for a bigger, more established engine so I went with Unity. Since I had never made a game with a first person view I felt like that would be a good start.
With some basic rules for myself I started to look closer at what would be fun to make. I looked at games I used to play to find something unique and fun that would still give me time to experiment. I ended up looking at 2 weapons from 2 different games. The Crossbow from Half-Life 2 and the 10mm HV Penetrator from F.E.A.R. Both of these guns have the unique property of when killing an opponent they carry their velocity over to the unfortunate npc and nail them to a surface.
Sticking to walls
The first step I wanted to achieve was to have a gun that shot nails that got stuck on surfaces. I started by creating a simple scene with some primitive geometry. Followed up with the creation of a character moved with the keyboard and rotated with the mouse.
I created a script for the gun that instantiated projectiles with mouse click and a raycast to see where the projectile would end up. The projectile that was instantiated held its own script that simply moved the projectile forward. With the built in collision detection the projectiles would collide with the wall and then fall down. With a collision callback I could parent the projectile to the wall but since it hits the wall with high velocity the projectile had time to turn and rotate at the point of collision. This made the projectile seem "weak" and not as impactful. The way I solved this was by checking if the object the projectile was going to collide with was a static object. If this was the case I turned off collision on the projectile and instead let it phase through the wall until the distance between the wall and projectile was small enough then just set the velocity of the projectile to zero.
Sticking to moveable objects
Using the above implementation for collision with an object that ifself can move would not be sufficient because any movement made by the hit object would not translate to the projectile. The solution that didnt work for my collision between static objects and the projectile worked well with the collision between projectile and movable object.
Since the object being struck will react to the impact the projectile will not have time to bounce of the surface before I parent it to the hit object. First iteration had some problem since the small interaction between projectile and object will only last for one frame before stopping the velocity of the projectile. I added an impulse force on the object after collision to ensure it bounces in the correct direction
Projectiles and small objects
The next step I wanted to accomplish was the ability to shoot at smaller objects and having them travel with the projectile until the projectile hit a wall. The main problems I found with this was the following
The object stuck to the projectile will clip into the wall they end up in.
The object stuck to the projectile will get stuck on the object its resting on if the angle of the hit is too low.
My solution to the problem of the objects getting stuck on their resting position was to remove the collision on the object being hit. Since it will move at high speed the player wont notice the edges of the object clipping through other objects.
The second problem was solved by adding a child that holds a local position centered on the projectile. When collision occurs with a small object I can then child the object to this point.
Now it was time for the main feature. Getting a humanlike character to stick to walls. I started of by placing a character down with no animations and a triggerbox that would activate when a projectile got close. When this happens the original character is destroyed and replaced by a ragdoll. This worked okay as long as we hit the joint directly connected to the root bone. For joints further down the hierachy the solution was to turn the affected joint into a kinematic object which forced the other joints to follow even if they were further up in the hierachy. The results were promising but one issue remained. Further hits on a character would stretch the joints.
Before fixing the final issue I decided to add some much needed feedback for the gun. These included
A muzzle flash particle effect
An impact particle effect
Camera shake when firing
Recoil when firing both on the camera and on the gun
Implementation was pretty straight forward. Particles are instansiated when firing and on impact. The camera shake is just a coroutine randomizing directions in x and y and the recoil is just lerping a value and adding it to the mouse delta aswell as lerping the gun model back and forward again.
Solving the stretching joints
The issue with the stretching joints were harder to solve than I though. I tried several solutions but they had their own problems
If a joint was too far away from the wall. The projectile would travel too far and not look connected to the joint
Colliding with a joint would push the joint to the side before freezing leaving it suspended in mid air.
If I attach the projectile to the wall behind the character any further movement from consecutive hits to the character will make the projectile look disconnected from the character.
Parenting the projectile to the joint will give a similar problem. Moving the projectile when the characters move but make the projectile look disconnected from the wall.
The main underlaying problem is that moving independent joints when their parent is kinematic will always cause weird stretching and jittering. But what worked best for me was to turn the affected joints rigid body into a kinematic type and do the same for its parent joint. This will stop most jittering and not give the joint thats hit any opportunity to move out of the way of the projectile since its parent will refuse to move. Unfortunately this wont give the player good visual feedback since the joint will just freeze and not show the force of the impact. This however solves the problem of the character looking disconnected from the projectile and vice versa.
When it comes to the problem of a joint being to far away from a wall when hit by a projectile. There doesn't seem to be a solution to this without moving the joints with will inevitably lead to stretching. One solution might be to check the length of the projectile and distance between joint and wall. If the distance is too large we use the same collision logic as we do between projectile and large object. This however will give an element of inconsistency in the experience.
If there was a way to ensure that ragdolls get stuck in a preferable position this might solve the problem. Maybe from increasing mass on individual joints or allowing a larger range of motion.
Example of a projectile freezing a joint but travelling too far
Best case scenario
Example of a projectile freezing a joint but travelling too far
The final product
Here we are 5 weeks later. We have a gun, we have feedback, we have bodies flying left and right making me look like a psycho when I apply for internship.
If I had more time I would fix some minor issues that happens when the projectile first hits a character. If the joint being hit is far down in the hierachy every other joint will have to correct themselves after the affected joint. This will cause the character to flop around violently for a couple of frames. Slowing down the projectile will make this less noticeable but at the same time take away the feeling of a powerful weapon when the projectile travels at a walking pace. Tweaking the drag, weight and range of motion on the joint might reduce the flopping aswell.
The capsule and sphere colliders surrounding joints could also use some size tweaking but reducing them might cause the character to intersect too much with the environment.