Backend
Overview
A game as mechanically intricate and reactive as Guncaster relies on well-designed backend systems to function smoothly. Systems that orchestrated gameplay states, saved and loaded player data, managed in-game interactions, and more. They compose the backbone of the project, and while sometimes invisible to the player work to make the game what it is. Many of these systems were designed from the ground up to be efficient, extensible, and highly modular. Their integration ensured the game remained performant and reactive, empowering the rest of the design to enhance player experience.
Contributed Breakdowns
BACKEND
Systems
These are Gameplay systems that make the core gameplay functional:
-
The entire Hierarchical Finite State Machine that all AI agents and the player inherit from. It was a good baseline to build from and had added benefits that helped rapid programming.
Featured exposed events for each states enter and exit. Helped streamline the implementation process.
-
Handles save and load functionality using JSON serialization combined with XOR encryption for lightweight but obfuscated storage.
modular saving, allowing specific systems to register their own save data.
Enabled the game to remember player progress, spells, stats, or settings across sessions.
-
Central interface for world interactions, like picking up objects, opening doors, activating triggers, and more.
Uses a clean interface-based architecture so that any object in the world can become interactable with minimal overhead.
-
Exposing certain animation parameters are a real pain. Instead I can OnStateEnter and OnStateExit manually set animation parameters based.
This cut down on overall work, especially on AI which were very event driven. I didn’t have to update the values for bools when an attack was over, it did that itself.
-
To ensure all computers can play our game regardless of tech level I integrated Unity’s pipeline switching at runtime.
Enabled players to opt out of high fidelity gameplay.
-
Consolidated repetitive Update() calls across dozens of scripts by allowing classes to register with a centralized ticking system.
Reduced per-frame overhead by grouping logic and giving finer control over when and how often systems update
Especially useful for AI, as it made it actually viable to have large amounts of agents.
-
Supports 3D and 2D audio, background music, and interface SFX.
Pooled audio sources for efficeny.
Implements dynamic music blending, allowing combat music to fade in and out based on combat.
Integrates with the Unity Audio Mixer, offering volume sliders and in-game pitch/time scale manipulation for stylized slow-motion effects.
-
Built on Unity’s new Input System, this manager provides a fully event-driven, plug-and-play input layer
Makes it trivial to map multiple input devices (keyboard, mouse, controller) and rebind them in real-time.
Other systems can subscribe to specific actions (e.g., Jump, Interact) rather than polling input manually, making input handling modular and responsive.
-
Orchestrated the game's state machine, managing transitions between menus, gameplay, paused states, victory/defeat, and more.
Broadcasts state changes to registered listeners using event-driven patterns, ensuring that all systems, from UI to the player, could react accordingly without being tightly coupled.
The literal core of the games states keeping the entire scene in sync.
-
A super simple Trigger script that allows the utilization of OnTriggerEnter and OnTriggerExit while exposing those as unity events
Additional Details
Beyond the backend scripts that made the game possible I included plenty of editor scripting. This ensured that our designers using the systems would have a good understanding of what exposed values did, how to set values correctly, and what systems the values would be affecting.
I did all those by heavily utilizing v0lt13’s Editor Attributes package. It’s a wonderful tool that allowed me to quickly whip up custom looking scripts without creating additional file bloat