Skip to content

Hold my Helmet Devlog: Five Weeks Into the Arena

The iron-bound gates of the Hold my Helmet gladiator arena standing open, with the title "Into the Arena"

How Hold my Helmet, our co-op gladiator game, went from an empty Unity project to Steam multiplayer, a Blender arena and a 97% cheaper HUD in five weeks.

9 min read

Five weeks ago this was an empty Unity project with one commit in it, called "Initial commit". Now there is a sandstone arena with a gate that creaks, a boss who walks out of that gate, a party of players who can take him on together over Steam, and a small pet who will happily carry a live grenade across the sand if nobody stops him.

The game is called Hold my Helmet. It is a co-op action game about gladiator trials. The party walks into the arena, an announcer calls the next trial, the traps wake up and a boss comes through the gate. Between rounds you spend what you earned on better weapons. Third person, physics combat, ragdolls, and a lot of things that explode.

This is the first proper devlog, so it covers the whole five weeks and then the last few days in more detail.

The numbers

Started8 September 2026
Commits73
Gameplay C#about 48,000 lines in Assets/Scripts
Test files71 (edit mode and play mode, mostly multiplayer)
Weapon profiles15, from bare fists to dynamite
Trap types3: pendulum, fire cannon, timed bomb
UI views11 independent HTML views
Playtests3 internal rounds, early October

Five weeks in five stages

Each stage ended with something we could actually play, which is the only reason they split so neatly.

Stage 1: a fight in an empty room (8–11 September)

Four days of getting a character to hit something. Animator, sword and bow animations, a boss and a spawner for him, a first arena. Then roughly one weapon a day: melee hitboxes, a bow that fires real arrows, grenades that fly in a proper arc.

On day three came the thing everything else now hangs off: the Arena Trial Director. It is one state machine that runs the sequence of trials. It opens the doors, lets the boss out, pays the reward and opens the shop for the break. Most systems written since then just listen to the phases it publishes. The same week we got trap logic, the shop (A. Luchikhin wrote that one), and body parts that can be knocked off and repaired.

Stage 2: systems (26 September – 1 October)

After a pause, a week of making things feel right. Full-body ragdoll. Jump and roll. Weapon equipment wired to the UI, plus in-game dev tools for testing.

The pet showed up here. He has his own state machine, his own navigation and a list of jobs. He follows you and picks things up. Yes, that includes an active grenade, and yes, it goes exactly how you would expect.

The arena also got a voice: an announcer character with his own animations. Bomb VFX and the fire cannon trap landed the same week.

Stage 3: multiplayer (3–6 October)

This was the hard part. In four days the game went from single player to networked co-op on Mirror, with Steam as the transport. Player spawning, a spectator mode for whoever is down, Steam names, an energy system for actions. On 6 October we built the first alpha.

Taking a single player prototype online mostly teaches you how many things you quietly assumed were local. These are the decisions that survived:

  • The host is authoritative. Damage, traps, the boss and the trial director all run on the host. Clients send what they want to do, not what happened.
  • Your own movement is predicted. The client moves at once, keeps a short history of inputs the host has not confirmed yet, and replays them when a correction comes back. Every packet carries the six newest unconfirmed commands, so losing one packet costs nothing.
  • Everyone else is interpolated from a buffer. Projectiles too, so an arrow flies smoothly on every screen instead of jumping.
  • Every entity has a stable ID. It never depends on the Unity hierarchy or on instance IDs. Boring to write. But it is what lets the host send a compact snapshot of the session to clients about once a second, which is the groundwork for restarting a trial cleanly and, later, for a run that survives the host leaving.

On the Steam side there are lobbies, friends, avatars, rich presence and achievements.

Stage 4: playtests (6–8 October)

Three internal playtests in three days, with a pile of fixes after each. The commit log for that week reads "fix 1", "fix 2", "fix 3", which is a fairly accurate description of what a playtest is. The fixes after the third one touched 244 files. Most of them were networked state that looked fine on the host and wrong on a client.

Stage 5: a real arena (8–10 October)

The prototype colosseum was a placeholder and looked like one. The new gladiator arena was built in Blender: sandstone walls with blood and soot on them, columns, iron-bound gates on real hinges, a boss chamber behind them and burgundy cloth stretched overhead.

Getting it into Unity was a small project of its own. There is now an editor tool, Tools/Arena/Gladiator Arena, that rebuilds the materials, prefabs and scene from the Blender export, so I can re-export the arena without fixing anything by hand. Trap mounts are sockets on the arena prefab. The doors are proper hinged objects, and their rotation is part of the session snapshot. The pet gets his own NavMesh for his agent type. Binary assets moved to Git LFS along the way.

All of that went in as our first pull request: 725 files, plus 51,000 and minus 21,000 lines.

The last few days

Sound

Until 10 October the arena made no noise at all. Now it has a proper audio system:

  • Up to 64 voices in a pool. When it runs out, lower priority sounds get dropped first, and the falloff curve always reaches silence at a cue's maximum distance.
  • A music director that crossfades between "waiting" and "fighting" depending on the arena phase. Under it sits a crowd whose volume follows the fight, with ovations when the boss walks in, when the fight starts and when you win.
  • Separate volume for master, music, effects, ambience and voice in the settings menu.
  • Sound that behaves in multiplayer. Footsteps, swings and pain grunts are worked out locally on every machine from movement, animation state and replicated health, so they cost no bandwidth at all. Things only the host knows about, a trap firing or a bomb going off, the host sends out as audio events.

A good part of the effects is synthesised by a small Python script in the repo rather than recorded. For a placeholder pass that is fast and keeps everything sounding like it belongs to the same game.

The HUD, split into eleven pieces

The interface runs on xploit_game_ui, the HTML/CSS/JS engine for Unity I wrote about a few weeks ago. Hold my Helmet is its first real user. For an engine that is the best and the worst thing that can happen.

The HUD started as a single full-screen HTML view. A health bar ticking down, the energy bar refilling, anything at all, and the repaint spread across the whole screen. So we cut it into 11 independent views: boss health, wallet, player status, party, weapon, trial, shop, main menu, revive, group window and a vignette. Each one is a small Vue project with its own texture, lifecycle and events. They build into StreamingAssets, and Unity creates them from one manifest.

I measured it on the real engine DLL with the CPU rasteriser, at 1080p, running the same scripted fight both times. The screen looks exactly the same. The bill does not:

MetricOne view11 viewsChange
CPU per frame, average282.6 ms9.7 ms−97 %
CPU per frame, p95506.5 ms15.2 ms−97 %
Pixels re-rasterized, total1,221 Mpx270 Mpx−78 %
Time to interactive291 ms191 ms−34 %
View texture memory7.9 MB15.0 MB+89 %
Compositing per frame2.07 Mpx2.70 Mpx+30 %

The CPU rasteriser is the worst case on purpose. In the game, rasterising happens on the GPU through Direct3D 12, so the absolute numbers are much smaller. What matters is the ratio: the HUD used to repaint the screen, and now each panel repaints only itself. It is not free. Texture memory doubled and there is more compositing. I would take that trade every time.

One more change I am happy about. The UI sources used to live in StreamingAssets, together with 162 MB of node_modules, and Unity dutifully imported all of it and copied it into the player build. The sources now sit outside Assets/, and only the compiled output ships.

How it gets made

The team is small, so the tooling does a lot of the lifting.

The arena and props are modelled in Blender, with export scripts so the round trip into Unity stays automatic. The HUD is laid out in Figma, and the views are built against the frame "HUD — Boss fight · Arena (1920×1080)". Every view also runs in a normal browser against a mock server, so most interface work never needs the Unity editor open.

Claude Code works across the whole codebase with us. Some of the biggest commits, the arena migration and the Git LFS setup among them, were made together with it.

What I want to do next

The trial sequence has three trials and one boss type for now. Bosses, trials and weapons are all ScriptableObjects, so adding more is content work, not code.

The snapshot and identity work from the multiplayer section exists so that a run does not end when the host leaves. The next step is actually handing the session over to someone else.

The arena needs a lighting pass, the boss chamber needs work, and the new materials have to hold up at the distance the gameplay camera actually sits.

And more playtests, this time with people outside the team.

If you have shipped co-op on Mirror and Steam and have opinions about host migration, I would really like to hear them.

Related posts

I built an open-source runtime that renders HTML, CSS and JavaScript straight into a Unity texture on the GPU. Why I did it, and what a frame costs.
#dev

I wrote an HTML/CSS/JS engine for Unity game interfaces

I built an open-source runtime that renders HTML, CSS and JavaScript straight into a Unity texture on the GPU. Why I did it, and what a frame costs.

Sep 23, 2026
Read More
Three days at ChinaJoy 2026 — the developer conference, the B2B floor, and the consumer halls. Who I met, what the AI tooling vendors are actually selling, and what surprised me.
#games

ChinaJoy 2026: What I Brought Back From Shanghai

Three days at ChinaJoy 2026 — the developer conference, the B2B floor, and the consumer halls. Who I met, what the AI tooling vendors are actually selling, and what surprised me.

Aug 11, 2026
Read More
I built a Windows tray widget that translates whatever you copied, text or screenshot, on a hotkey. Here is what was actually hard about it, and it was not the translating.
#ai

XPLOIT Translator: A Clipboard Translator That Lives in the Windows Tray

I built a Windows tray widget that translates whatever you copied, text or screenshot, on a hotkey. Here is what was actually hard about it, and it was not the translating.

Aug 7, 2026
Read More

Newsletter

Occasional notes on engineering, game tech, and new tools — no spam, unsubscribe anytime.

Andrei Rovnyi

Engineering manager, founder, and software developer building web platforms, game systems, real-time services, and automation tools. 15 years of shipped work — currently at Gaijin.net.

Get in Touch

Building an MVP, shipping a game feature, or automating a team workflow? Open source or paid — let's talk.

Contact Me
© 2020-2026 XPLOIT FZE. All trademarks, names and logos belong to their respective copyright holders.