TECHNICAL DESIGN & PROTOTYPING
F P S
In December of 2019 I set out to make a multiplayer first person shooter.
What’s in a game?
Understanding the constraints solo developers grapple with — I often found myself setting aside my dream of making a multiplayer FPS to work on my more achievable ambitions. It wasn’t until I had copious amounts of time quarantining during the Covid-19 pandemic that I was suddenly blessed with the ability to take this concept off the backburner and finally delve into what some of my favorite games are made of.
As brief a forward as this is, I feel that I should mention the absolutely disgusting amount of time I’ve dedicated to Rainbow Six: Siege, Call of Duty: Modern Warfare (2019), and the Battlefield franchise as well.
In no way do I feel limited to the FPS genre in terms of my design interest, but I kept finding myself being drawn back to them as a gamer.
The following is a technical breakdown of some of the more interesting challenges I encountered developing a networked FPS prototype in Unity 2020. Enjoy!
ART DIRECTION
I started with a mood board, a collection of visual references, to kickstart the ideation process.
RETICLE
This one’s for the fans of "Hardcore” — not just for the sweaty headclicking or the friendly-fire but for the lack of UI clutter which, in turn, can often heighten player immersion. For this game, I opted out of incorporating a screen-space reticle purposefully, thereby forcing the users to participate in diegetic view finding methods. Figuring that I’d already implemented a procedural animation system for weapon bobbing and camera sway I thought the next reasonable step would be to completely refactor my recoil system and apply the animation offsets to where the player will shoot.
What this ends up creating is a random, yet deterministic, system for impact logic. So long as the player aims where their reticle (or laser sight) is pointing, they’ll hit their shot. This prevents players from drawing a dot in the center of their monitor or memorizing recoil patterns while still giving them the ability to subconsciously learn the bullet mechanics of the game.
A somewhat-intended side effect of this is how useful reticles now are. Not only is there a benefit to the magnification from the scope but they are the only surefire way of calculating where you’ll hit— save for the laser sight.
Laser sights give the player a huge advantage in the sense that they can now line up shots from the hip and not just when aimed-down-sights or ADS. Plus, they don’t suffer from the depth of field blur when ADS as the scopes do. They do have drawbacks though:
They can be seen by other players
They don’t remove the sometimes obtrusive ironsights (worse picture)
No magnification upon ADS
Smoke grenades will reveal the entire beam, broadcasting your line-of-sight or LOS to your enemies
RELOADING
From correct slide placement to whether the magazine ejected from the gun is fully depleted or not— small inconsistencies can break the illusion and the players’ immersion. These beautiful animations are the creations of David Stenfors but are executed using a custom built state machine (animation controller) that is easily expanded with the use of Animation Overrides:
These overrides are intended so that technical artists could import new animations (or overrides for entirely new weapons) with ease.
The base animation controller supports pump and bolt action firearms out of the box. Watch as these guns reload the correct amount of ammunition:
Another animation controller was created for the corresponding third person puppet that blends between source animations using networked parameters mapped to the horizontal and vertical axis.
RECOIL
Not unlike most first person shooters, holding down the trigger yields a much wider vertical and horizontal recoil spread. This project uses a bespoke Scriptable Object type to house all of the data/information about each gun, allowing frontend developers to balance and add new weapons through GUI.
Since we now have this exposed Scriptable Object type, we can tweak the horizontal and vertical recoil patterns respectively.
We’ve also made sure to have the first pellet launched from the shotgun always hit it’s center mark—
if you get a headshot you get a headshot.
INHERITANCE & WORKFLOW
In order to streamline the process of making a multiplayer experience, most networked interactions are routed through a central event manager.
This Network Event Manager exposes the ability to call events from anywhere. By consolidating all event calls here, implementing new events and calling them from recently added classes is highly simplified. This significantly expedites the process of sending and receiving data from other clients through the server as there’s no need for redundant code throughout the repository.
We then can utilize a Network Event Listener to expose callback functions to any class that inherits from it. This gives us a foundation for players, controllers, and anything else that needs to be networked and interactive to react globally across all client machines.
Why not take it a step further?
The Controller Listener not only has access to network events, but also latches onto whatever controller (character) the desired player has been assigned. It can choose to only listen to the local client (for example, a post-processing effect that is triggered by your character getting shot) and also can reassign itself to a new controller upon respawning or joining a new lobby at runtime.
In the fourth slide we inherit from the Controller Listener type to create a Controller Muzzle Flare than can emit particles whenever the controller it’s listening to fires.
Controller Listeners are implemented throughout this project, ranging from basic UI HUD elements displaying ammunition count to the entire Controller Puppet — the third person character model that corresponds with the player’s movements.
LEVEL DESIGN
Well what better a level to create for QA’ing than the infamous Shipment from the Call of Duty franchise? Shipment features a claustrophobic multi-lane layout that works particularly well for deathmatch and can be deceivingly complex on more objective-based game modes (such as Hardpoint and Gunfight.)
This low-poly recreation was fabricated with assets by Synty Studios and managed to be strikingly accurate considering the modular prefabs it was made with.
PLAY TESTING
. . . . is not always as fun as you might think it’d be. There’s a lot of unchecking things you thought you’d fixed off the task list that, apparently, you hadn’t. Playtesting can also be pretty demoralizing when you’re staring at a grey-boxed environment like this all day:
Besides, level design is integral to game design and fundamentally changes the way people will play the game. I’ve personally found it to be well worth it to invest in building a testbed that allows for rapid iteration and encourages your play-testers to exploit every possibility in order to win.
Gameplay footage of an extremely informal playtest.
CONCLUSION
A lot of time has gone into the development of this project, including a twin repository in UE4!.
This was an exercise in technical game design and pipeline engineering, and a real eye-opener to what goes into creating a functioning multiplayer FPS title. Everything, down to pooled bullet collisions and casings, can factor into the development & prototyping of a playable first person shooter.
Solid technical design will save valuable developer cycles on potential refactors later on down the line. My key takeaway is that
the initial time investment of building a comprehensive framework, such as this one, significantly accelerates the roadmap of future multiplayer projects.