Leaving Unity Behind: How I Stress-Tested Godot for My Massive Indie RPG by Prime Games Bulgaria

Leaving Unity Behind: How I Stress-Tested Godot for My Massive Indie RPG

Leaving Unity Behind: How I Stress-Tested Godot for My Massive Indie RPG
Why I switched engines, mixed C# with GDScript, and how I plan to handle standard development bottlenecks in Godot.

Every Hero's Journey reaches that pivotal moment where you must leave the familiar Shire behind and step into the vast, unknown wilds. For over eight years, Unity has been my steadfast companion. Together, we crossed valleys of despair, shipped commercial titles, and built a sustainable indie game dev endeavor. But after my latest main project, Fabled Lands, finally came to an "end" (no, don't worry! it's not a closed page, but it has reached some logical closure for the time being), I found myself at a crossroads.

When you are running a bootstrapped indie business, analyzing your ROI and technical debt is a matter of survival. The recent, well-documented changes in the engine's ecosystem didn't just feel like generalized industry drama; they made a huge dent in my trust, directly impacting my livelihood and the long-term sustainability of my work. Between the constant deprecation of features, half-finished directions, and the increasingly heavy load of the editor, my old companion just didn't feel the same.

I needed to reclaim ownership over my tools. Enter Godot 4. The fact that Godot is completely Free and Open Source Software (FOSS) is absolutely incredible. There are no licensing fees, no sudden Terms of Service rug-pulls, and no corporate overlords to answer to. If something breaks, I can literally look at the engine's source code. For a solo indie developer running a business, that level of freedom and security is invaluable.

Today, as I build my next massive interactive RPG, Blood Sword, I can confidently say this engine has brought back the joy of game development. It genuinely motivates me to open the editor every morning and just work.

But I didn't just jump in blindly. Here is a deep dive into how I tested the waters, structured my new technical stack, and ultimately built the confidence to commit a multi-year RPG to this engine.

Testing the Waters: From Mobile Ports to Desktop Releases

Before committing my next multi-year RPG to a new engine, I needed to know if Godot could actually handle the real-world indie dev pipeline. So, instead of a simple prototype, I tackled three distinct smaller projects to put the engine through its paces.

The MVP: A Pocket-Sized RPG
My first foray was a simple yet intricate companion app for a gamebook. Essentially, it was a pocket-sized RPG, complete with character stats, ranks, skill trees, equipment, inventory limits, spells, and automated text combat. A perfect sandbox for a programmer to test the waters and see how the engine handles spinning up fresh RPG mechanics from scratch!


The Rebuilds: Transomnie and Battle for Murk
Next, I rebuilt two of my past projects from the ground up: my 2017 mobile app Transomnie and a complete rewrite of my smaller 2D desktop game, Battle for Murk.

Tackling Transomnie took just 2,500 lines of code to handle UI, XML parsing, custom interfaces, input systems, and production builds. Meanwhile, Battle for Murk allowed me to test the desktop and Steam pipelines. While Murk successfully proved the publishing flow works, its currently non-existent player base means I haven't yet been able to verify how Godot holds up against thousands of wildly different PC hardware configurations in the wild (more on that later).

But from a purely developmental standpoint, across all three projects, the results were eye-opening:

  • Localization: Godot's native solution is incredibly impressive. Everything from fonts (and specific characters), images, and audio to translation tables is built right in.
  • Mobile Deployment: Adding templates for Android and iOS was smooth. I actually lived to see a project with zero XCode warnings!
  • Desktop Publishing: Releasing smaller proof-of-concept PC games later on, I discovered you can sign and notarize your Mac app directly from within the engine. (You still have to staple it manually, but Mac devs know the pain this saves).
  • Steam Integration: Using a third-party GDScript add-on, Steam integration took exactly 10 lines of code. Boom. Achievements done. (Next up is exploring Good Old Games' wrapper!).

The Editor Just Gets Out Of Your Way

Godot simply doesn't get in your way. The editor is remarkably lightweight; it runs beautifully even on my 2015 MacBook Pro, complete with a proper debugger.

Coming from a background in web, Java, and C#, Unity's older UI system often feels like an archaic Java behemoth from the Netbeans era. Performance-wise it's terrifying you every time the Garbage Collector hits or the whole Canvas gets dirty. Godot's UI, by contrast, felt superb. You throw a lot more Nodes at a problem than you would in Unity, but it's cheap enough and gets the job done natively. As the younger folks say, the engine just has "rizz" - it has a flow that lets you focus on making the game.

The Architecture: Composition Rules!

I initially had reservations about moving to a dynamically typed language like GDScript, missing my interfaces and generics. But Godot's cross-scripting ideology is brilliant. My approach to the codebase is simple: Deep data-driven composition.

While Unity is famously component-based at the Scene level (attaching MonoBehaviours to GameObjects), doing the same thing purely in data using ScriptableObjects can quickly become rigid and clunky. Instead of doing everything in one language, I mix them to get the best of both worlds:

  • The Data Layer (C# .NET): I use C# purely for data and heavy algorithms. This handles the interactive story logic, pathing, and distance calculations for turn-based hex combat. Plus, I still get to use my favorite NuGet packages!
  • Managers, Controllers, and View (GDScript): GDScript handles the rest. I use it for my game managers, controllers, and all presentation logic. And honestly? No matter if I'm using the internal editor or VSCode and GitHub Copilot, writing GDScript is an absolute joy.


Bridging the Divide: Pragmatic Marshalling
To keep the C# and GDScript completely decoupled, I utilize an Event-Driven Architecture with a global EventDispatcher Autoload.

But passing complex objects back and forth between languages can create engine bottlenecks. Coming from enterprise software, you might default to strict type-safety across the board, but indie development requires pragmatic trade-offs. To bridge the languages, I marshal data across the boundary using Godot's native Variant Dictionaries. It sacrifices strict cross-language typing, but it radically speeds up solo development and completely bypasses the marshalling overhead.

I'm also keeping a close eye on the community's progress. There is currently an active PR to implement a trait system in GDScript. While it's not on track for the immediate next release just yet, it looks incredibly cool and shows the engine is constantly evolving toward cleaner, more modular code.

Solving the Narrative Bottleneck

Interactive storytelling is the lifeblood of Prime Games. I've used Inkle's open-source #ink language since 2017, and Blood Sword is a massive game - easily 5 to 10 times bigger than standard benchmark projects.

Godot has two great Ink integrations: one in pure GDScript (inkgd) and a C# solution (godot-ink). However, for massive stories, official benchmarks of inkgd note that the pure GDScript port can be up to 50 times slower due to object allocation bottlenecks.

Because of how easily Godot lets you mix languages, the fix was simple. I integrated the highly performant C# godot-ink solution to handle the heavy lifting of story generation. But I didn't just plug the integration in - I built a custom C# text lexer/parser on top of it.


Because RPGs require complex gamestate mutations, my parser intercepts my own custom Ink tags (like >>>STATS, >>>ENDURANCE, or >>>COMBAT) directly from the manuscript. The C# layer acts as the brain, translating those narrative cues into backend logic, while seamlessly passing the final visuals to my GDScript UI layer. For the player, it's instant magic. Problem solved, zero performance drops, and an incredibly scalable narrative pipeline.

The Big Test: The June Demo

Unfortunately, it's not all roses. The scariest part of learning a new engine isn't the code - it's the stability in the wild.

This June, I am releasing the first public demo for Blood Sword. This will be the ultimate trial by fire. What I need to find out is exactly how stable a Godot game is when exposed to thousands of players. Will I face unexpected crashes? How will the engine handle compatibility with the massive, diverse variety of gamer hardware setups?

But having successfully ported and released those smaller projects over the last year, I feel prepared to tackle whatever the wilds throw at me. Rather than a scary unknown, this upcoming demo is the ultimate, exciting equation waiting to be solved by my new tech stack. My only lingering concern is how a solo dev tackles Nintendo Switch support, but I know that's improving in the ecosystem.


The Shire is behind us. The wilds await. Stay tuned for the Blood Sword demo this June!

Comments