← Back to all projects

Splish-Splash Submarine

Uppsala University

7 7 weeks

Splish-Splash Submarine

Lead programmer on a 7-person submarine shoot-'em-up with a horror-comedy streak: I built the team's balancing and deploy tooling, and the design fix that got players shooting instead of dodging.

UnityC#Jira

I was the lead programmer on this, though it was never an official title. Two of us wrote code, and I owned most of the architecture and committed two to three times as much. I had a playable prototype running by the end of the first day.

I was also the most active person in our design meetings, and a lot of what shipped came out of them, including the dodging fix above.

The rest of my time went to tools. I came in with around seven years of Unity, and none of my teammates had worked in it before, so a lot of what I built was about lowering the barrier for them, even when that meant making something I didn’t need myself. The most useful ones collected data that Unity usually spreads across many objects. The balancing setup kept every design value in one file, so when a teammate flagged an issue mid-playtest, they could find the value behind it without hunting through the scene. I did the same for audio: one list of every sound effect, so our audio person could wire up SFX from one source while I referenced sounds in gameplay before the real clips were hooked up. I also built a one-click deploy so non-technical teammates could push a build to itch without going through me.

  • Modular scriptable objects for hot-swapping balancing configs

    1. The problem

    Balancing a game means constant value-tweaking, to the point where tracking how all the numbers interact starts to feel like alchemy. I wanted to try whole configurations, store them, and compare them across playtests instead of editing values in place and losing the old ones.

    2. What I built

    The format let me give every configuration a name and a bit of metadata, so a config like “SprayNPray” (a high-frequency shooting setup) was self-describing instead of an anonymous block of numbers. Values were split into Scriptable-Object modules by system (Player, Shooting, Enemy, EnemyFromBehind), each with its own variants, and I’d compose a few into a full game mode, saved as its own file to load during playtesting.

    3. Retrospective

    The shared modules had a catch: because each was a single asset, a value I tuned to make one mode feel right silently changed every other mode that used it. Deciding module boundaries was its own puzzle, too (does Shooting belong inside Player, or stand on its own?). Even so, one access point for every tuning value was a clear win. Nothing was scattered across GameObjects and Components anymore, and switching between game modes mid-playtest was effortless.

  • Why playtesters were dodging instead of shooting, and the mechanic that fixed it

    1. The problem

    During playtests people were dodging enemies instead of shooting them as it was easier to simply avoid them. It’s a shoot’em up and people weren’t engaging with the core gameplay.

    3. A redesign that didn't ship

    My first pitch was to lean into what the players were already doing and make dash (dodge) the main verb: The enemy behind you closes in, which pushes you to dash clear of it. You still technically aim and shoot, you’re just “shooting” yourself and instead of enemies, you aim at the gaps between them. This made dashing dual purpose: dodge enemies, evade lurker. Dashing rapidly naturally makes the game harder as you need to find an opening faster, which kept it balanced for the players who’d otherwise breeze through the level. That one mechanic handled both the rear enemy and the dodging. The team voted it down for a fair reason: it takes shooting the enemies out of a shoot-‘em-up.

    2. Requirements
    • Players must not ignore enemies
    • Game needs to distill dread
    • The big lurking enemy ever present from behind needs to catch up to you somehow
    4. The redesign that shipped

    With the redesign out, I needed another way to force shooting. What I did was make enemies you don’t shoot reach the bottom of the screen and auto-latch onto your sub like a parasite, slowing you down for a while. Slowed, the lurker can start creeping on you, distilling dread. Since one leech detaches after some time you’ll need a few for the lurker to catch you.

    5. The result

    This not only forced players to shoot, but also got us much closer to the desired experience. Once a leech latches, there’s no immediate fix. You can only attempt to stop a second one from landing and hope it detaches before the lurker reaches you, and that elongated helplessness distilled dread far better than what we had before.

  • Inbuilt deploy button for one-click WebGL → itch.io uploads

    1. The problem

    Deploying a WebGL build to itch meant building it, manually swapping in the custom HTML and CSS, then uploading with a butler command in the terminal. It was a programmer-only routine, so during playtests non-engineers couldn’t ship a fix without me.

    2. The tool

    A dead simple Unity editor button that builds the game, swaps in the custom WebGL HTML and CSS, and uploads to itch via butler in one click, no terminal required.

    3. Impact

    Any teammate could push a hotfix mid-playtest, and everyone’s build updated automatically through the itch app. The custom HTML wrapper came along for free.