Development
Prototype
When beginning development, a previous small project was referred to when implementing both a character controller and simple agent navigation system. It’s fairly rudimentary and utilises many built in Unity components but provides for an incredibly useful jumping off point for this project. Especially as it was produced as part of college learning that gave a helpful understanding of the systems behind it allowing for further innovation. Afterward, a hit scan weapon was implemented utilising a Raycast, a useful way of connect two objects (French, 2021), in this case to find what the player is looking at. This Raycast will incur the “GetShot” function in the Agent script, damaging the enemy, seen in Figure 1 The weapon was originally going to utilise a projectile with travel time, however this felt unresponsive and didn’t fit with the simpler gameplay style. An issue arises with the lack of a cooldown on the weapon, allowing the player to deal damage every frame, definitely overkill for the enemies 3 health. To prevent this a cooldown system, taken from FaffyWaffles(2021) on the Unity forms, was implemented using Unitys “WaitForSeconds” function to suspend the coroutine for the given cooldown time (Unity Technologies, 2024). Whilst there are further plans for ways to communicated to the player that they shot or that their cooldown has ended, for the sake of the prototype, the weapon will simply change colour alongside the crosshair. All this, combined with giving the enemy an ability to damage on a cooldown reused from the weapon script, has led to a very early prototype of the main mechanics of the game, Seen in Figure 2.

Figure 1 - Code behind Raycast weapon
Figure 2 - Early prototype showcasing weapon and enemy
Enemies
The first major innovation came with the development of the enemies. Instead of creating multiple copies of the agent script to create each enemy, the agent script is set as an abstract class containing all the functions every enemy will utilise. The individual enemy scripts will only need to contain the enemy specific stats, like health, damage and speed, along with unique enemy abilities, such as projectiles. This will help immensely with debugging, allowing for large sweeping changes to be made to the agent code, whether due to bug fixing or a change in design, without the need to go through each individual script. This also provides an easier way to implement more enemies, and whilst there are no plans to, it accounts for potential further development. This assisted in the development of the enemies, seen in Figure 6 and whilst learning and utilising more advanced skills with classes took time, the project still remained ahead of schedule and progressed the goal of furthering personal technical skills.
Figure 6 - Progress of enemy types, including enviromental damage and bullet
HUD
When implemented a prototype version of the heads-up display (HUD), the planned UI design took up a large amount of valuable screen real-estate, seen in Figure 3, especially as there isn’t a reasonable amount of information to populate the HUD. Whilst the design was initially planned to emulate the UI design of Doom (1993), as mentioned earlier, it stands to reason that many of the design elements are out-dated or made due to the hardware limitations at the time. Instead, a recital health bar was used, inspired by the bar of the Legend of Zelda: Breath of the Wild (2017). Using a visual way of representing health can more clearly portray the data to the player without requiring them to take attention away from the gameplay to read it, it can also provide users who may struggle with reading disabilities a easier way to digest important information. After following a tutorial by Game Dev Guide (2019) to implement a dynamic progress bar system, it was hooked up to player health points and made dynamic, making any balance changes made to player health automatically apply to the UI, seen in Figure 4.

Figure 3 - Initial prototype of HUD

Figure 4 - Finalized health HUD
dialogue
When creating the dialogue system, initially the entire code from a previous project was recycled, however, this posed more of a challenge. Since the whole project was built around the dialogue, a lot was built on top of the original script, with many features that are unneeded for what is required in this project, such as multiple dialogue options and responsive emotions. So instead of trudging through and tearing apart the code to work on this project, it was considerably easier to start from scratch and readapt the dialogue system by John French(2023), especially as the personal knowledge was already there if the code needed to be altered. It also came with the added benefit of including a way to speak to the character your facing, something that was removed from the previous project's code, allowing for multiple characters to easily be spoken to when found. The only additions required was a prompt to inform players they could interact with the character, finalizing the dialogue system seen in Figure 5.
Figure 5 - NPC interaction and dialogue.
Save system
Since there is no prior personal experience developing any sort of save system, a tutorial by Kaupenjoe (2023), seen in Figure 7, was followed, both demonstrating and explaining the code behind a save system. Making the ‘SaveData’ script a singleton, by setting a public static instance of itself within the script, allows for it to be globally accessible (French, 2021). This is convenient as it’s an important game system that, given the large encompassing scale of the save system, will require many scripts to access it, enabling an easier connection of systems within the game (French, 2021). On the contrary, it can negatively impact performance to located the save data manager in the scene every time a new object is created (French, 2021), especially as the project gets larger. Alongside this, the script being accessible from anywhere could lead to issues surrounding overlapping variable names or broken code influencing the script from obscure locations. Whilst there are further ways to enforce security or performance, due to the planned scale of this project and the time allocated, the current system provides more positive and time spent improving the system would be inconsequential as it has no signs of interfering with current code or influencing the games performance.
As seen in figure 7, the original code was based around directly saving and loading in player stats, where-as this projects use case requires saving after certain events, such as dialogue interactions or enemy defeats. This required a slight altercation to the dialogue scriptable objects, introducing a “index” integer, that, when ran through the dialogue system script, will set the assigned character as discovered, as seen in Figure 8. An inherit issue with this and the save system is the undynamic and hard coded nature of it, requiring each unique save variable to be individually added into the code in multiple places. Not only is this tedious, it means that any changes made to the planned saved elements required going through the save system script and ensuring everything is correctly updated, increasing the chance of bugs and wasting development time. And whilst it would be proactive to update the code to be iterative based on the number of saveable elements in case of any required changes, the planned saved elements are set in stone and regardless of the expanding scale of this project, the save system will remain mostly unaltered. After adding all the save elements and connecting up the number of enemies defeated to the system, has led to early debug version of the save system, Seen in Figure 9.
Figure 7 - Tutorial demonstrating a JSON based save system, used for this project.


Figure 8 - Code of Dialogue System and Dialogue Scriptable Object, responsible clocking and saving dialogue interactions.
Figure 9 - Debug version of menu and save system (With commentary)
Archive
Initially, each entry in the archive would be created manually, and the respective entries would be deactivated and activated. However, there is no current consensus on the number of entries planned, and it would be more fun and beneficial to develop a dynamic system. In the end, scriptable objects were used, as they’re useful for saving a large amount of data whilst reducing the project's memory usage and can be easily altered in the Unity inspector (Unity Technologies, 2024). The main issue with the archive it breaking when exiting the bounds of the entry array. As seen in Figure 10, by using the modulus operator to return the division remainder of the archive index by the archive array length, it will always return a valid position in the archive. However, an issue arises when going under the index array, as C# incorrectly calculates the remainder of negative numbers. To solve this, the archive array length is added to the archive index, ensuring that the position of the archive never falls into negatives.

Figure 10 - Code behind looping archive
It's important to show the player where in the archive they are, however, it felt uncreative and gave off a very unfinished feel to display the position with numbers. In previous projects, a large amount of code was used to dynamically set the scale and position of UI elements based on the amount. However, after watching a video about UI design by Mark Brown of Game Makers Toolkit(2025), Unity’s layout groups were brought to attention, which would automatically align any children of the parent object (Unity Technologies ,2024). This considerably expedited the process of correctly aligning elements and allowed for the final archive system, seen in Figure 12, to be developed quickly and to a high standard, perfectly encapsulating what I had for the archive system.
Figure 11 - GMTK video about UI design
Figure 12 - Archive system with placeholder entries.
Audio
As mentioned in planning, this production follows a more waterfall-oriented workflow. To complement this, despite sound design and audio over-hall being planned later in the project, developing and implementing the systems the sound design will use is important. A notable development was the voice acting. Initially, a bunch of empty game objects with audio sources attached would be activated and deactivated depending on the corresponding voice clip to be played, as suggested by m0ds (2022) on Reddit. However, it was quickly made apparent that this would be an incredibly tedious and unoptimized way of implementing voice acting. So, instead, the dialogue scriptable objects were updated with an audio clip section, as seen in Figure 13. That, when running the dialogue, will assign said audio clip to the audio source, making the system considerably more dynamic. Allowing for voice acting to be implemented, as seen in Figure 14.

Figure 13 - Scriptable Objects behind dialogue and voice acting
Figure 14 - Sound system demonstration
Concluding Development

Figure 15 - Archive system with placeholder entries.
Figure 15, would you look at that, a (nearly) clean ClickUp board, what a beautiful sight. Ideally, it would’ve been fun to implement the different poses on the menu screen. However, as the development stage draws to a close with all planned features having been implemented, the project is on time and on track to begin the level design. Full speed ahead!