Back to Design Notes

ThunderBashers: shipping a Unity brawler in five days

5 min read postmortem unity jam game-feel ai-design

ThunderBashers was built in about five days for the Very Serious Juniper Dev Game Jam, theme: Spin To Win. Solo on design, direction, art, and audio. It went live on itch.io as a WebGL build with a Windows fallback. It’s my third shipped jam game and my first in Unity, after Spare Knight (Phaser 3) and I Won’t Be Abducted (Godot).

The pitch

Robots in a circular pit bash a storm-charged ball at each other. Spinning is your only verb: it strikes the ball, it parries an incoming hit, and it shoves a rival in close. Get touched by the ball while you’re not spinning and you’re eliminated. Last bot standing wins. The theme wasn’t a layer on top of the game — spinning is the offense, the defense, and the win condition.

I wrapped it in a deadpan corporate framing: the THUNDERBASHERS PRO LEAGUE, a sanctioned robot-combat circuit whose Standards Committee insists the rules are fair. The tone was free points on a jam that rewards “serious,” and it gave every bot a reason to exist.

The whole game was there in the first napkin sketch — the robots, the spin, the ball. Most of the five days was the distance between this and a build that felt like it.

Early concept sketch: the robots, the spin, and the ball

The pivot

I started the jam in Unreal. Half a day in, it was clear the engine was spending my time instead of saving it: no clean WebGL path, slow iteration, and every hour in the editor was an hour not spent on art. So I pivoted to Unity with about five days left.

That was an eyes-open trade. It forfeited the “Best Unreal Engine Game” prize. But Unity ships WebGL, which means the game plays instantly in a browser on the itch page — more plays, more ratings — and it opened a “Best Web Game” target instead. The Unreal start isn’t deleted; it’s parked for a hands-on Unreal project later. Switching engines mid-jam sounds reckless, but the real risk was finishing nothing, and the pivot was the move that protected shipping.

The mechanic that fought back

The core rule — the ball kills you if it catches you not spinning — should have been the easy part. It was the hardest thing in the game. It felt wrong for days, and the temptation was to keep re-tuning the rule.

The control scheme was simple from the start — move, mouse to aim, space to spin — but “simple to operate” and “feels good to play” turned out to be very different problems.

Early controls sketch: move, mouse to aim, space to spin

When I actually root-caused it instead of symptom-chasing, “the mechanic is broken” turned out to be about five separate problems stacked on top of each other. Any touch killing you made parrying feel like an alien timing-puzzle bolted onto a brawl. Over-correcting to a speed gate made enemies basically never die. The ball kept parking in a dead-zone speed band that read as neither safe nor lethal. One value was gating both a bot’s offense and its defense, so tuning a bot to be beatable also made it stop fighting. And the ball would look red-hot while the kill-check briefly read it as safe after a wall bounce.

Each “fix that didn’t fix it” was fixing a real bug — just not the one in front of the player that minute.

Readability is a mechanic

The fix that finally made the core feel right wasn’t a rules change at all. It was a progressive heat-tint on the ball: cool blue when it’s slow and safe, ramping to red-hot and crackling when it’s fast enough to kill. Suddenly “a slow ball doesn’t hurt you” reads as intuitive instead of buggy, because you can see the threat state. The single biggest feel win in the whole game came from legibility, not from changing what the game does.

That’s the lesson I’m keeping: when a mechanic feels wrong, it’s often a readability problem wearing a rules problem’s clothes. Fix what the player can see before you change what the game does.

The thunder-ball glowing red-hot — the danger telegraph

Bots with temperaments

It’s a solo game, so the bots are the game. I didn’t want a difficulty slider; I wanted opponents that felt like they had personalities. So every bot is a data profile — reaction time, aim error, spin skill, how far ahead it looks for an incoming ball, how readily it panics — and those profiles fall into five archetypes from a newbie that mistimes and feeds you confidence kills to a veteran you can only beat with wall ricochets and baited parries.

Two bugs taught me the most. Bots crowded the ball and multi-killed in one pass, looking dumb — fixed by electing a single “committed striker” each frame so they approach one at a time. And splitting offense from defense (always strike, parry by skill) was the unlock that let a bot be tuned beatable without going passive. The campaign then just distributes those archetypes across three arenas to build the curve.

What I’d keep

Root-cause, don’t symptom-chase. The shipped build is the only build that matters, so build to your real target early. And readability is a mechanic — the most legible version of a rule usually feels like the best-designed one. A small, finished, legible game beats a big unfinished one, every time the clock is running. </content>

Let's build something.

chrisdalbano12@gmail.com

© 2026 Christian D'Albano · Hand-built design system — Nuxt 4, Tailwind, motion-v. Tokens and motion vocabulary by me.