Molementum is a 3D party action game where you assume the role of a mole criminal to rob mines of their precious gems. Grab up to 3 friends and scramble your way through mines while engaging in various acts of competitive mischief as you try to become the most notorious mole criminal.
Networking
Molementum is an fast-paced online multiplayer game. Players use Lobby Codes to join each other's games. Players have the ability to customize their names and appearance. As it is a non-competitive party game, we opted for a host-client structure.
I have been working with Unity Netcode for Game Objects since VizBoXR in 2022, and the updates to the framework since then have coincided well with my speed of learning the best approaches to take.
Packages and Frameworks Used
- Unity Netcode for Game Objects
- Facepunch.Steamworks (.NET wrapper for Steamworks API)
- Unity Services
- Lobby
- Relay
- Authentication
- ParrelSync (for developers)
Lobby Management
Molementum has a private lobby-code lobby system utilizing the Unity Lobby and Relay services. This system is completely decoupled from the rest of the game, meaning it could be used easily in other multiplayer games in the future.
Supporting Multiple Backends
By utilizing polymorphism, I was able to quickly develop separate backend Lobby systems that utilized Unity Services and the Steamworks framework. We chose to take advantage of both, so that we could allow Steam users to invite their friends easily, but also release a playable build on Itch.io.
In the future, I would consider using Dependency Injection to allow for Steam users to switch backends if they would like to play with itchio users. We also considered a setup that allowed for a lobby with both advantages, but lacked development time to explore that.
Code Structure
This code snippet should give you an idea of the basic structure of the abstract class.
These events are mostly useful for UI updates, as well as notifying game systems if a player left early.
Public virtual properties with protected set components offer greater flexibility for derived classes. They can be overriden like a getter method, or be set directly inside of other methods.
The LobbyManager class contains a number of methods that act like this: A public method that handles validation and then calls abstract methods.
This snippet also demonstrates use of asynchronous methods and .NET Tasks.
Modular Systems
Molementum contains many interlocking systems, such as tiered upgrades, complex physics-based movement, and dynamic gameplay objectives. It was my responsibility to create the backend for these systems in a way that enabled a decoupled codebase and synergistic gameplay.
Tiered Upgrades Backend
Players obtain upgrades for their mole at the beginning of each round of gameplay. These upgrades vary greatly in behavior and occasionally synergize with each other.
Upgrade Behavior Types as Interfaces
Upon discussion with designers and consideration of design documentation, I divided upgrade functionality into 3 categories: Active, Passive, and State. Some upgrades required behavior linked to multiple categories, which led me to decide to utilize interfaces to represent each category. The interfaces indicate the required functions for the desired upgrade, while the Upgrade class contains backend functionality for setup, cooldowns, transmitting events, and more. All interface methods are exclusively called by the Upgrade base class.
Part of the reason for this approach was to enable the use of a finite state machine within the player controller. During early prototyping, another programmer had developed a system which required two separate classes for each state-linked upgrade. Through discussion with the programming team, we designed this structure that would allow one script to act as both an Upgrade and a State.
This is the entirety of the IState interface. The comments are verbose to help enable code-proficient designers to implement upgrades themselves.
The IState interface is divided into state machine functions, and state validation functions.
ShouldRemainCurrentState and CanBeEntered are separate functions primarily to facilitate states that initiate by launching the character from the ground and continue until landing.
Quick Templates Development Tool
To better facilitate rapid development of upgrades, I created a tool to automatically generate a script that indicates what needs to be implemented. The tool also creates a linked ScriptableObject, which is useful for tweaking values in SerializeFields.
The script on the right of this is a script generated with the requested interfaces: IActive and IPassive.
I also created a detailed presentation to explain the intracacies involved with creating new upgrades. Designers and programmers both told me they greatly appreciated this level of communication.
Game Architecture
Player Systems
Molementum's player requires a large amount of systems that are somewhat intertwined. Upon deciding on final design for the gameplay loop, I created and implemented a new structure for the Player scripts, which would allow for decoupling of the various Player systems.
Manager and Access Point
The Player script serves as an access point for all Player subsystems. It also manages the subsystems, dictating update execution order, and enabling/disabling certain systems depending on the game state.
Having a central access point like this helps to enable a events-focused approach. For example, the PlayerAudio script listens to several events in other player systems to know when to play sound effects and voice lines. This approach also helped debugging since we could easily track the order that player systems operated in.
Networking was separated into its own script by splitting its behavior into two types: local and non-local. On the local player's player object, the PlayerNetworker listens to events and transmits necessary info across the network regularly. For all other player objects, the PlayerNetworker outputs events, which other scripts listen for. With some exceptions, the PlayerNetworker is treated similarly to the InputManager in these circumstances.
Game Management
The GameManager takes a similar approach to the Player script with a manager class. The GameManager is the only Singleton class in Molementum, and thus acts as an access point for the many events and objects. The subsystems of the GameManager have almost no reliance on other GameManager subsystems. The main exception is the Scorekeeper, which acts as an event listener.
LobbyManager, InputManager, PlayerSettingsManager, and RoundManager are all subsystems, which could be wholly removed from this game and put into others. The RoundManager manages game phase changes. Some game phases involve a scene change and others do not.
The ActionPhaseManager and DecisionPhaseManager are the most complex systems as they dictate the core flow of the game. They each have their own subsystems, which could be explored in more detail.
Credits
Designers
If you are looking for any other roles, I would strongly encourage taking a look at my teammates' portfolios linked above. They are all extremely talented and great to work with. I could not have asked for a better team.