Adventures with Guns in a Third Person Shooter
May 10, 2011
Today I’m going to discuss third person shooters (3ps) and some lessons I learned working on Monday Night Combat. If you have worked on a 3ps before then this post will contain few, if any, surprises. It is however useful knowledge for many games and genres.
Monday Night Combat
In a typical 3ps, such as Gears of War, the camera sits behind and above the character’s shoulder. The further away the character is from the camera the harder your life becomes. Here is a set of screenshots showing the Tank character from MNC who is wielding a rail gun. Take note of the relationship between the character, camera, and tip of the rail gun’s barrel. They are fairly far apart and this will soon prove to be quite painful. :)
There is a discontinuity between the character (Tank) and the camera/player (human holding a controller). What are the implications? To be honest, a lot. Today I’m going to focus on one in particular. What the player views (third person) is different than what the character can view (first person). This causes issues when it comes to firing guns.
Let’s take a first pass implementation on a gun. Our Tank character has a rail gun which will fire a single shot. We will perform a ray trace from the camera through the screen centered crosshairs to determine a hit location. If we were working on an FPS this would work pretty well, but alas we chose to do things the hard way and made a 3ps instead. What is our problem scenario?
Uh oh. The left half shows a blue Tank where the character is behind cover, but the player has clear line of sight to an enemy. The right half shows an orange Tank being shot at by a completely covered shooter! The blue tank is shooting through world geometry and this is clearly unacceptable.
Currently the trace origin is the camera location and the trace direction is the camera direction. What if we move the trace origin to the barrel tip but kept the camera direction? This doesn’t work at all. Both FPS and 3ps players expect that when an enemy is in their crosshairs and they pull the trigger it will do damage. If we move trace origin to the barrel then the crosshair does not precisely match where the gun will actually shoot. This will not suffice.
What if we dynamically move the crosshair? This was tested for MNC, but it causes the crosshair to jump around causing a confusing and unpleasant play experience. Some FPS games do this when you stand close to world geometry and it works well for them. Serious Sam does it I believe.
It is critical for the trace to come from the camera for the controlling player to have a positive play experience. It is equally critical that the player not abuse the environment. What’s the solution? We perform an initial trace from the camera origin into the world to determine a hit location. A secondary weapon trace is then performed from weapon barrel tip to the initial hit location. If the weapon trace succeeds then behavior and damage is as expected. If it fails, by hitting a wall 6 inches in front the character for example, then the new hit location is used.
The larger the screen space distance from the barrel tip to the crosshairs the more often the weapon trace will fail. Most guns are held against the shoulder which has a short screen space distance and players won’t notice a thing. Guns that have a minor zoom feature shorten the distance even more. Unfortunately our poor Tank has chosen to be gangsta and shoot his rail gun from the hip causing him to miss his desired target more often than others. This isn’t necessarily a bad thing. It is also an art issue in some regards so be sure your art team is aware of the ramifications.
We have a pretty good solution, hooray! Are we done? Of course not! This is a video game, and lord knows there are always edge cases. Look at following screenshot.
The player should clearly be able to hit the enemy in both cases. What happened? The camera trace hit the enemy, but the weapon trace hit world geometry so no damage was dealt. Damnit. The weapon trace prevents players from firing behind cover, but in this case it is the enemy who is partially covered. How do we fix it? The weapon trace is simply given a maximum distance (empirically tested to ~7 meters). The goal is to prevent the player from shooting behind cover and a 7m check successfully does that.
Is it perfect? No, but it’s good enough. Short geometry can block shots in a surprising manner and shooting down from a platform can be problematic. These issues go away with shoulder-planted weapons.
Visual effects still start at the weapon barrel so although the traces are clear the effect may clip geometry (image below). I expected the community to complain but it turned out to be a non-issue. First, it’s hard to notice at game speed. Second, damage should be dealt so nothing feels broken to either player.
Are we done now? Nope. Some guns, such as a sniper rifle and Tank’s rail gun, have a penetrating shot that hits multiple targets. Our ~7m weapon trace goes towards the camera trace’s hit location, but with multiple hit locations what do we do?
Let’s assume a single penetrating shot hits 5 targets. We could perform weapon traces to each target and only do damage if the trace succeeds. That seems a bit wasteful. It is also possible for some weapon traces to succeed and some to fail. Maybe the target in the back takes damage but not the one in the front. Talk about weird and confusing! For MNC we settled on a single trace from the barrel tip to the furtherest hit location. If that weapon trace succeeds then all targets take damage, and if it fails the new hit location is used.
Are we done now? Haha. Of course not. Our current traces are from the camera and barrel tip. This isn’t enough. Examine the following.
On the left the sniper rifle sticks through world geometry. On the right the force field is from the player spawner — orange team can walk through, blue can not, and it stops all bullets. In both cases the barrel tip is on the other side of collision geometry. The first case could be fixed if character collision encompassed the weapon, but the second could not. What’s the fix? For MNC we perform a third trace from the character’s hand to the barrel tip. Characters use cylindrical collision and so long as their hand is inside that volume it will work.
At long last we are done! Monday Night Combat solves many third person weapon related issues by performing three ray traces.
- Hand Trace from character hand to weapon barrel tip.
- Camera Trace from camera origin forward into the world.
- Weapon Trace from weapon barrel tip to camera trace hit location.
It’s worth discussing other games for a moment. Did you know that many first person shooters don’t have effects that fire from weapons in multiplayer? They fire from the character’s forehead! Don’t believe me? Check out this shaky cam shot from Halo Reach.
Those sons of bitches! The gun is shoulder high, but those tracers originate from the forehead plain as day. Reach is actually a little odd. If player 2 views player 1 shooting the effect comes from the forehead. However, if player 1 views players 2 shooting the effect comes from the barrel. This means that the visual effect can clip through world geometry. Why the difference? It is a mystery.
Gears of War 1 tracers play from weapons, but all shots can go through geometry while standing or in cover. If the weapon barrel clips into world geometry then the shot will hit the wall.
In Gears of War 2 tracers again come from weapons. Players who are in cover can shoot through walls.
Players can even shoot through the geometry of their actual cover. The human is using a van for cover and can shoot through. (Gears 2)
However, if the player is standing in the exact same position then they can not shoot through. (Gears 2)
When using cover an animation usually causes the player to expose themselves. Some situations, such as the van, allow the player to “cheat”. I believe this was allowed because some cover has irregular geometry that would block legitimate shots. Options are to change the geometry, change the animation, or let the player shoot through.
Team Fortress 2 fired effects from the nose initially, but has since been updated. Insomniac’s FPS Resistance has an interesting solution for multiplayer. Effects start from the barrel, but quickly curve to lineup with the first-person nose trace. In Call of Duty, thrown tomahawks spawn on the forehead. Every game has unique and slightly different behavior if you look closely.
I want to take a second to thank Uber Entertainment’s badass technical artist Ben Golus. He was instrumental in writing the weapon systems for MNC and answered countless questions on weapons for effects for virtually every major game ever released. He answered even more questions as I wrote this article and even took the shaky cam pics you see above. Thanks Ben!
There is no one size fits all solution. All games handle things a little bit different. The Tank rail gun issue is one that I found to be both interesting to solve and surprisingly deep. What seemed simple upon cursory glance took an engineer and technical artist to hammer through a dozen possibilities to find a fix that was functional for both gameplay and visual effects. I found the issue fascinating and hopefully others do as well.