Two developers built a game that sold 1M copies. How?

The Pragmatic Engineer 1h29 7 min #23
Two developers built a game that sold 1M copies. How?
Watch on YouTube

Summary

  • Jonas Tyroller, one of the two developers behind the indie strategy game Thronefall, walks through how the game was built, how it sold over a million copies in its first year, and what it’s like to develop games as a two-person team using Unity, C#, and Blender. The episode covers the full journey: from rapid prototyping and finding a marketable idea, to technical architecture, pathfinding challenges, difficulty balancing, porting to Steam and Switch, and the practical (and impractical) development habits of tiny indie teams.

The prototyping process: make a lot of tiny games, then pick the best one

  • Jonas and his co-developer Paul spent roughly two months building one-to-two-day mini-game prototypes in Unity, exploring ideas like a flower-spreading game, a climbing game, and a card game.
  • The goal was to find the overlap between something they wanted to build and something that could sell — finding both at once is the hardest part of indie game development.
  • They eventually landed on a simple 2D prototype: a castle in the center, a controllable figure, enemies approaching, and a day/night rhythm of building and defending. Both immediately recognized it was far ahead of everything else they’d tried.
  • After the gameplay prototype was locked in, they ran a separate visual prototype phase — starting from an empty project with no code, just experimenting with camera angles, zoom levels, and visual styles, collecting hundreds of screenshots on a mood board before settling on the flat-shaded minimalist look.
  • They went down at least one dead end: they spent about a month building a card-game version of the kingdom management concept before scrapping it. Jonas describes this as a relief — better to fail fast than spend two years on the wrong idea.

How Thronefall is built: Unity, C#, scenes, and assets

  • The entire game is written in C# using the Unity game engine. Unity handles rendering, physics, and much of the heavy lifting.
  • The main organizational unit in Unity is a scene (essentially a level). Each level is a scene, and the menu/level-select is another.
  • Within scenes, everything is organized into GameObjects, which can have MonoBehaviour scripts attached — these are C# classes that define behavior, state, and logic.
  • 3D models are made in Blender and imported into Unity. The integration is tight: updating a model in Blender updates it in Unity.
  • The toon shader (handles the flat-shaded cartoon look, shadows, and outlines) was bought from the Unity Asset Store — a common shortcut for small teams. Unity also ships with many built-in shaders that cover most needs.
  • The A pathfinding system* was also pulled from the Asset Store and then customized. It uses a node graph overlaid on the ground, where each triangle is a node. The graph is dynamically updated when the player places buildings.
  • The game’s download size is only about 100–200 MB, because textures are minimal (flat-shaded style), 3D models are tiny, and C# code is compact. The largest assets are the music and sound effects — Jonas composed the music himself.

Pathfinding was the hardest technical problem

  • The biggest technical challenge was getting units to navigate the node graph correctly. Units can collide with each other and with walls, and different unit types have different movement rules (some can pass through walls, some can’t, flying units ignore terrain).
  • The team had to maintain separate node graphs for player units, enemy units, and flying units, because each has different passability rules.
  • Even with a purchased pathfinding plugin, there were persistent issues: units getting stuck on corners, enemies attacking walls as if they could walk through them, and the need for post-processing to smooth paths so units don’t move in jagged lines along node edges.
  • Despite these issues being noticeable to the developers, most players never noticed — a reminder that “it works” often matters more than “it’s elegant.”

How a two-person team actually works

  • Jonas handles gameplay programming, content creation, balancing, and music. Paul handles UI/UX design, art, and visual polish.
  • UI work is a surprisingly large chunk — roughly 40–50% of the total effort — because it has to support mouse, keyboard, and gamepad input, look good, and handle every overlay, menu, and settings screen.
  • They communicate less as the project progresses: heavy communication during prototyping, then by the end of the project they talk maybe once a week and both just know what needs to be done.
  • They always try to keep the game in a functional state with every commit, so either person can test it at any time. This becomes critical as the team grows, but even at two people it prevents constant frustration.

Indie development practices that would horrify big-engineering teams

  • No unit tests. Jonas is open about this. Indie games operate below the scale where unit tests become necessary for maintainability. Debug prints and manual testing are the norm.
  • Push directly to main. They don’t use feature branches or pull requests. This works because they ship infrequently (not continuously deployed), and the game is always kept in a runnable state.
  • No code review. Jonas acknowledges it would be beneficial, but the culture of indie development prioritizes speed and momentum. He notes that ChatGPT can serve as a rough substitute for code review.
  • The host pushes back gently but ultimately agrees: these practices are context-dependent. What works for a two-person team shipping a game to Steam every few years is very different from what’s needed at Uber-scale continuous deployment.

How they used feedback to shape the game

  • They gradually expanded their testing circle: starting with a small trusted group, then a wider circle of testers, then Early Access where every buyer was effectively a tester.
  • Building upgrades (choosing between different tower types) were not in the original design. Early testers said the game felt too rigid — you couldn’t customize your buildings on predefined slots. The team added upgrade choices in response, which became a core part of the game’s appeal.
  • Enemy-dropped gold was also added after launch. It smooths out the economy’s snowball effect (where being ahead makes you further ahead, and falling behind makes recovery nearly impossible), making the game easier to balance.

Difficulty balancing and the mini-games

  • Strategy games like Thronefall are inherently snowball-heavy: small advantages compound, making games feel either too easy or too hard with little middle ground.
  • The base levels are intentionally on the easier side. The mutator system lets players add difficulty modifiers for a harder challenge.
  • The mini-games (bonus modes) are deliberately very hard — they’re an outlet for Jonas to experiment with wild ideas using existing systems. After players complained about their difficulty when they were placed alongside regular levels, the team moved them further into the game so they’re clearly marked as endgame content.
  • Jonas notes a common developer trap: he’s much better than the average player, so he has to consciously make levels feel “stupid easy” for the best players. Top players can beat most levels with just the king, without building a single structure.

Porting to Nintendo Switch and the business side

  • The Switch port was outsourced to Warp Digital, a porting studio. The deal is a revenue share — they handle all the porting, publishing, and platform compliance. This is the same approach Jonas used for his previous two games.
  • For indie developers, Steam is the primary market — it’s roughly 90% of revenue. Console ports are a bonus on top.
  • Launching on Steam is “surprisingly anticlimactic” — there’s a button in the Steam backend, a few confirmation dialogs, and then it’s live. Launch timing matters less than you’d think because everyone tries to pick the optimal date, which cancels out the advantage.

Gen AI as a development tool

  • Jonas uses ChatGPT (and occasionally Claude) extensively. His main workflow: write skeleton code with function signatures and TODO comments, then have ChatGPT fill in the implementation. This works especially well for boilerplate.
  • He also uses it as a translator for unfamiliar domains like Shader code — pasting in code and asking what it does and where to modify it.
  • He hasn’t tried GitHub Copilot because he wants to use AI intentionally, not have it constantly running in the background. He’s wary of it disrupting his workflow or creating a habit of relying on it when he shouldn’t.

Advice for software engineers who want to make indie games

  • Don’t build your own engine. Use Unity, Godot, Game Maker, or Unreal. Speed is the most important thing for a small team, and building an engine from scratch is a massive time sink.
  • Don’t over-engineer before validating fun. Resist the urge to build complex systems (like an MMO backend) before you’ve confirmed the core gameplay is enjoyable. Figure out the experience first, then engineer it.
  • Pick a very small game. Games don’t sell better just because they’re bigger. A game made in half a year has much lower financial requirements to be successful, and there’s a real market for small, focused experiences — especially among people with day jobs who don’t have 80 hours to finish a AAA game.
  • UI is underestimated. Budget significant time for menus, settings, input handling across devices, and overlay systems.
  • Bureaucracy is the worst part. Taxes, legal documents, Steam paperwork, and deal negotiations are the least glamorous and most annoying part of indie development that nobody talks about.
  • University was valuable mainly for the people, not the curriculum. Jonas studied game design at HTW Berlin and met Paul and other collaborators there. The courses were useful but self-teachable; the curated cohort of motivated people was the real value. When evaluating a game school, look at how selective the admissions process is — harder to get in usually means better people to meet.
  • Success requires luck, but also market awareness. You need to find the overlap between what you want to make and what people want to buy. It’s not enough to make a great game — it needs to be the right game. Use the ice cream metaphor: perfect garlic ice cream is still garlic ice cream. Make great ice cream in a flavor people actually want, and don’t set up next to ten other stands selling the same thing.
Back to The Pragmatic Engineer