Breachers

Breachers

Role: Gameplay + System Programmer
Size: 4 people
Time span: 4 months
Engine: Unity 6

About

A tactical team-based VR shoorter.
A VR shooter featuring vaulting, climbing, rappelling and strategic teamplay. In 5v5 matches players use a mix of guns and gadgets to outsmart and outplan the opponents.

Short-form summary:

My follow up project at Triangle Factory after Hyper Dash
Packed with knowledge about the company and our systems, I got to tackle a whole new and larger codebase.
My favourite experience was the sleeker and more defined standards and naming.
An example is having a tighter naming convention surrounding networked values and them being state/client auth, which HD did not have.
Some of my core contributions feature:
- Many bugfixes for guns, player interactions, ui interactions
- A brand-new gadget: The C4
- Throwing trajectory system, used for reworked grenade death recap (small but cool)
- Rework on networked functionalities


Introduction:

Breachers is a succesful VR shooter game by Triangle Factory.
It features bomb plant/defusal as it's main gamemode but also has a team-deathmatch and elimination mode.
The core gameplay loop uses a variation of guns ranging from pistols to heavy rifles. They're supported by gadgets such as grenades, drones, breaching foam, clone projectors and more.
Actions in the game earn the player money which they can spend on these tools, as well as add attachments to guns.

Entering the project, I could immediately notice that the codebase was bigger, but more readable and understandable than HD. While I did have a lot of experience with that project, the simple differences of stricter naming and general structure of the project made it easy to navigate. I do think my experience as a programmer over the last months helped a ton as well!

I got to work on this project from June - September.

My contributions:

Developing a new gadget: The C4

C4 png

The C4 was my first big task where I got the creative liberty to prototype and work on a throwable C4.
Although it might sound simple it had a lot of features and challenges to it!


1: gadget-on-gadget


The C4 is a gadget attached to a gadget.
This caused a lot of hickups with the lerping of positions and parenting of one gadget to another.
It's never been done, but it was an amazing opportunity to delve into the networking of Breachers opposed to Hyper-Dash.
It uses a newer version of the package and has a very different implementation and way more features.

I've gotten a much deeper insight on networked order execution, optimisations, and lerping data with its networked side.
Having prediction work properly while slowly going to the requested throw from the server was important as it does have to feel smooth for both parts of the gadget.
It was a challenge to get both the parented movement of the two gadgets working well, but also having it stick properly on the wall.
I used a combination of its hitbox and then projecting its touchpoint on a plane compared to the wall, to have it rotated and placed nicely.

Challenge 2: equipmentSlots


The second challenge to tackle was to have a nice visual for the detonateable brick to slot onto the detonator.
We already have equipment slots on the body, which I thought could be reused nicely.
Confidence and experience helped me a long way here! These equipmentslots were deeply rooted into the character, grabbing and slotting code for gadgets and weapons.
I had done similar tasks on HD on a smaller scale, but I abstracted the class to its base functionalities and split it up into a normal equipmentSlot and a gadgetSubslot.
Applying the networked side went fast as I already had experience with it from before, and the smaller tickets I worked on before helped a ton with already understanding the grabbing and slotting code.

Challenge 3: Complexity of the smaller aspects


One of the things I tried working on more is overthinking the smaller things.
Something I had to pull myself back on was the picking up system. By default we can set pickups per team or mode.
For this there was some complexity in who can pick up the detonator and the brick, or together.
I used previous experience to write down the logics on pen-and-paper.
To spare you the web there were a ton of conditions and triggers that would(n't) allow you to pick up either, and visualising it before doing it helped in finding similarities and making a state-machine like diagram.
An extra part of the challenge was reusing our UI system to add a new type of icon to indicate where the brick is when holding the detonator, as well as indicating its armed state for teamplay.

A smaller task with many insights: The throwing-arc

My ticket was to include a thrown line into the death-recap of the grenade.
Immediately a few ideas came up in my head:
1. Make it reuseable
2. Minimalize and customize points used in the arc
3. Take into account the network-authorative throw, not the locally predicted one

In the end I managed to lower the points sent through the network to +- 2-20 points.
When touching new colliders and having certain minimum changes in velocity I take note of their location and velocity on server.
Then I do a recreation of these points on client-side, using the dot product between the object and its target, and the velocity's direction to see if its passed its target.

What's important is how I learned to tackle this task efficiently and optimally.
After finishing a good version of the ticket, I reworked it and abstracted it to its core useages and changed the grenades code to being reuseable static functions.
It's now a .cs file with functions that can calculate trajectories in various ways, and it can output these with customiseable aspects. (eg. points output in total vs points per x time passed)
An elegant implementation that is now fully disconnected from the grenades, and in its core only tens of lines.
However, the math is well-thought out, the functions are useable in many situations, and I still kept in mind general coding standards and practices for smaller choices (an example is overloading vs different functions).

Building expertise in Networking

Another task, which due to NDA I cannot give specifics about, was to improve on an older system related to networking.
It was something in consideration for a very long time and I was happy to do it as it was within my interest field and Networking has been something I've grown a larger passion for.

The task was to analyze the current state of a system and see what can be improved.
It concerned the lerping of data between a networked and non networked lerp. A three-in-one Lerp spaghetti!
The biggest thing I took away from this task was to be critical of existing code. I might be a junior, but it's a topic I've worked quite a bit on in this project, and part of the task is to improve, not just create new things.
I tested the system thoroughly and marked the hitches and parts I did not agree with.
After communicating with my lead, I looked further into techniques related to networked interpolation and handling of data.
The decision was made to rebuild this part from scratch, which came with other problems as implementing new things we wanted was going to add in new edge cases as well.
I got to delve more into math surrounding polynomials and types of interpolations, as well as write down notes on how to use the system and continue on it.

The pitfalls of prediction are mainly that you have to give up some correctness either on server or client.
I used some measures to get them more correct such as using the time value between the sending/receiving of the package to correct on the other side, but this can't always be correct and needs to be supported by the networking system.
Client-correctness means it will visually look nicer, server-correctness will mean less frustrating ghost-hits and represents what actually counts for the server. Choices, choices, choices.


What did I learn?

Personal

1. I like working in a codebase for a long time. It's a bizarre thing to type out, but I found a deep appreciation for having my place in a company. I like staying in and being part of a team and getting to know the codebase by heart.
2. Natural critical thinking and ownership
  Also mentioned in the practical skills, I do consider this a personal skill as well. I've gained a shift in mindset from intern to collaborator on the project. I'm stronger in my shoes to not just accept the status quo on a project and dare to suggest meaningful improvements.
3. Having a strong voice is good
  As a programmer, junior or senior, you're there to give opinions and thoughts. You won't get shot in the street for speaking up, it's expected. I've grown stronger and have less fear in talking up and voicing thoughts. Systems can sometimes change, and implementations can be (sub)optimal, and the space needs to be safe to discuss these things.
4. Applying my people skills in a lead-like role
  I've got a lot of experiences in different teams, but it's my first time assigning tasks to others and making the calls. My future goal will always be to become a lead in a project when I'm ready for it, but it was reassuring to having experience with the responsibilities in this role and it's given me confidence in myself as a person!


Practical

1. MORE NETWORKINGGGGG
  It's something I got to do a ton more again in this project. It's been fun and insightful and I'd love to take on a personal project to explore networking in Unreal as well. This is planned to start in November.
2. Confident refactoring
  Touching existing code has always been slightly scary as an intern/junior. I've gotten used to changing code now, and I've had the chance to be allowed to change systems intertwined with many others. I've grown from trying and figuring out to confidently architecting and refacturing large features
3. Code cleanliness & reusability
  I've abstracted and decoupled many parts of the codebase by now and can confidently say they're part of my usual repertoire when thinking what needs to be done in a ticket.

Relevant Links

- Breachers Meta Quest
- Breachers Steam
- Triangle Factory Website
- No direct code snippets as I'm under NDA. Do feel free to ask me about general implementations regarding these topics and any coding related questions are of course also welcome!!!