Platform:
Windows PC
Overview
As a cataclysmic event rocks the planet, you find yourself in an antiquated submarine tasked with only one goal: survive and reach a deep water facility. Manage the internal systems onboard the sub to keep yourself alive and fend off undersea horrors as they attempt to cut your journey short.
Thalassaphobia is a short, immersive horror experience that was originally created for the Brackey's Game Jam 2023.2. Our intention with the game was to tap into the feelings of claustrophobia, panic and helplessness that the deep ocean invokes.
Engine:
Unity Engine 2022.3.1f1
Programming Languages:
C#
Duration:
11 months
Tools Used:
Git, Visual Studio, Photoshop, Audacity
Completed:
May 2024
Team Size:
Total: 10
Design/Programming: 3
Audio: 1
Art: 5
Animator: 1
Role:
Technical Director/Creative Director
Project Goals
Create an immersive horror experience that derives from feelings of loneliness, confinement, and the lack of control that being in the deep ocean brings.
Complete the game to a high level of polish
Refine our teamwork as a small development team
Experience the publishing process
Contributions
My role on this project was technical director/creative director. I fielded implementation questions. I kept the project heading towards its intended experience and made sure that we didn’t bite off more than we could chew in the short deadline we were allotted. I set expectations for when features should be delivered as well as monitored their quality.
Some of my major contributions to the project include:
Steam Integration and Achievements
Localization/translation
State machine that controls the behavior and spawning of the monsters
Interactable system and the code for the kinesthetic levers/plunger/valve
Made use of event systems and abstract classes to allow for agnostic, scalable systems, and allowing new mechanics to be created modularly
Shaders (Toggleable emission masks and blending between the fixed and broken window states)
Persistent user settings
Animation events
Scene transitions and load screens
and much more!…
Highlights
We had seen some promise in the game. The team had come together and decided that we wanted to continue development on Thalassophobia and see what it became. We fixed several bugs from the original version. We added several monsters and ship mechanics, improved the responsiveness of the game’s controls, fixed many bugs, and overhauled the game’s balance to be easier than it’s initial version.
Around this same time, myself and a few artists from the project started attending a small indie developer meetup that occurs at least monthly in East Austin, Austin Games Y’all. Their events range from book club style discussions about games to showcase events where developers come to show off their project and gain exposure. After attending a few of their meetings, we pitched to the team that we wanted to get the game ready to show at their October showcase. (Link to event details) Everyone agreed and so began a sprint to get the game prepared for the event. We got through it, and the game was bigger, and more stable than it had ever been. We were excited to show off the game.
It was a sobering experience. We did not receive much positive feedback beyond the sympathetic players. The increased complexity of the game, as well as the loud and busy environment we were showcasing in had caused a familiar problem to rear it’s ugly head. The game wasn’t clear enough. The tutorial caused too much friction. The feedback was not clear enough and did not come through enough channels. It was clear to the team that a pivot needed to be made to fixing these core problems. A game is only as good as the experience it gives to it’s players, and we were giving people bad experiences.
Monster State Machine
State Manager (Github)
Sped up final behavior
Abstract State Base Class (Github)
As we added more monsters, it was apparent that we’d need a manager to share data between them. I decided to utilize the state pattern to solve this problem because none of our monsters could occur simultaneously. I used abstract classes to create a blank state that was used to define the interaction between the state machine and the individual monster state. I then inherited from the blank state in each one of the individual monster states. From that point it was as simple as filling in the blanks for each monster’s behavior.
The final version contained five states; an intro state, an idle/waiting state, the eyeball state, the tentacle state, and the worm state. The final behavior was such that you would enter the game, the intro sequence would play and the player would have a period without any monsters to acclimatize to the submarine and listen to the intro dialogue. That is followed by the idle phase where the player is left in the ambience and their resources start declining. Right around the time that the player will need to refill on oxygen, we bring in the first monster. From that point, the state logic forms a loop. The idle state waits and spawns a monster while preventing repetition. The monster comes out. It does it’s intro. It then it begins all of it’s runtime behaviors. Once the requirements for warding off the monster are met, it returns control to the idle state.
Sticking to this design pattern lead to easier understanding from other programmers, easy diagnosis of bugs, well encapsulated logic, expandability, and modularity within the system.
Steamworks Integration & Achievements
SteamManager.cs (Github)
Tutorial with explanation of some design choices
Part of preparing for publishing was adding Steam integration and achievements to our game. I wrote this Steam manager to easily debug, reset, and grant achievements to players. I used an index naming scheme for the achievements and interacted with it through an enumeration to make the code more easily understood and implemented.
Blog
Thalassophobia began as a game jam game for the Brackey’s Game Jam 2023.2. It has since grown into a polished and fully released Steam title. Throughout the project, we've had the privilege of experiencing several significant firsts in our careers. We’ve gotten to see the first content made about a game that we made, we got to represent one of our projects at an event, and we went through the publishing process. Each has reminded me of a platitude that gets thrown around constantly in this industry, “Game development is an iterative process.” Just like trying to teach your children about your mistakes, it’s difficult for young developers to grasp just how foundational this sentiment really is until they’ve been there yourself.
Shortly after our initial game jam release, we were tipped off that a YouTuber had made a video about our game. For the first time, someone had made content about a game we had made, and they had made the game look really fun! It was exhilarating. Everyone that worked on the game was quoting it and gushing about it after it’s release. It was a great moment of solidarity and camaraderie within the team.
Although the overall message was positive, it’s important to remember that even if someone is expressing their enjoyment of your game. They still have a ton to teach you about what is wrong with it. In this video, you’ll notice that when he reaches the tutorial, the pacing of the video comes to a complete halt. Showing that this large word dump was causing an extreme level of friction to our players. You can see him toggling mechanics that he doesn’t mean to be toggling and then correcting, a problem with labeling. You can see him failing to interact with the levers several times.
At the time, these were problems, but they were not priorities. These weak spots were to become recurring characters throughout the development cycle of the game.
The final leg of our journey encompasses the time from showcasing our game at Austin Games Y’all to our steam release. We removed the tutorial in favor of a “phone guy” style narrator the first time you play the game. We added tons of feedback to existing actions; more sounds, more material changes, more animations. We kept iterating and slowly rounding off all of the rough corners that the project had.
The experience of going through Steam’s integration, review, and publishing process was slippery but overall very manageable. It’s given me some real experience working under NDA. The integration itself took very little time, just a day of fiddling around and it was fully implemented. Integration went pretty smoothly, taking only a day. Deciding on the logistics, branding, and marketing side of publishing took significantly longer, being updated consistently as our release approached. I worked closely with Roarke Estrin (LinkedIn) to make sure that everything was up to our standards and matched the tone we were trying to convey.
At the time of my writing this, it’s the day after release. The game has only received good reviews thus far. We’ve made back the money that we put into publishing. I’ve learned a lot while making this game. I come back to that platitude I mentioned in the introduction, “Game development is an iterative process.” I’ve come to find that, it’s not a suggestion. It’s a rule. Plans often don’t work as foreseen and future changes impact old design. Something in the game will always be able to improve. You need to get something on that page before you can improve it though. Don’t get bogged down in asset ownership and ego. It’s ok for people to work on your stuff. Everyone on a healthy team is looking to make the game as good as they possibly can.
In conclusion, stop waiting and make the game. Planning gets you to the starting line but iteration will get you to the finish line.
Scalable Resource Systems
There are several of this similarly constructed systems throughout the game. I’m going to be covering the power system for this highlight since it’s the most complex of them. The process here was relatively simple. The resource manager holds a list of active users that is populated by the individual scripts that inherit from the electricity user class, and each frame it sums up the total cost of the active users and broadcasts that change over an event.
Sped up final behavior
Abstract Electricity User Class (Github)