Greetings, fellow indie devs!
As the creator of the "Oni Hunters" / "Minimon" series, I've seen the game development world evolve drastically over the past decade. From the old times where most of us had in-house engines to the modern era where Unity was the indie king, the tools have been ever-changing.
This weekend, I undertook the challenging task of porting my latest game from Unity to Godot.
Read on to discover the hows, whys, and lessons learned!
Unity has served many of us well for years. However, their recent decision to retroactively change their terms of service, especially after earlier assurances to the contrary, has severely eroded the trust of many developers, including myself, prompting us to seek alternatives.
Enter Godot, a rising star with great C# support. As a complete newcomer to Godot, I was curious to see how my Unity experience would transfer over.
The "Magic" Behind The Quick Port
I can almost hear the collective gasp of developers reading this – porting a full game to another engine in a mere weekend?
Especially considering the scale of "Oni Hunters", with its decade-long legacy, an expansive 4GB repository containing an assortment of almost 3000 assets (sprites, audio, maps, etc), paired with upwards of 500 C# scripts. Sounds almost impossible, right? But, there's a method to this madness, a secret recipe that made it all possible.
The secret lies in an engine abstraction layer. Burned in the past by tricky porting experiences, I was adamant about future-proofing "Oni Hunters". By limiting Unity-specific dependencies to a mere 3 source files and a clean scene architecture, the groundwork was laid for a seamless porting experience. This might not be feasible for everyone, but for devs who focus in 2D retro games like me, it's a goldmine of time-saving potential.
Essentially, my strategy was all about creating my own API, a protective layer that sits between my game and the engine, keeping my game logic insulated from the specifics of any engine. To put it simply, it's like crafting a custom interface with tailor-made for your game's needs. Taking the example of a 2D RPG game, this API would house straightforward methods such as
CreateActor(), StartBattle(), and so on.
For the asset side of things, I made my maps engine-agnostic by creating them outside of Unity using Tiled. For things like sprite sheets, I made sure I followed a specific size convention for every one, that made it simple to automate splitting them into individual frames and animating it.
I've seen this approach being called different names among gamedev circles, from "code-driven development", "scene minimalism" or "runtime scene generation". The gist of it is keeping the Unity scenes mostly empty and then drive the majority of the game logic and content through C# scripts. While you continue to leverage Unity's core capabilities, the emphasis slightly shifts from the editor. That said, the editor remains crucial for real-time inspections and modifications.
While this approach demands an upfront investment in time and planning, the flexibility and independence it offers in the long run are invaluable. No matter how deeply an engine embeds its claws into the industry, with the right abstraction, my game remains liberated and agile. I understand it's not an approach suitable for everyone.
Digging Deeper into DIY Solutions
Now, I can almost hear the virtual gasps and immediate counter-questions from some of you. "What about all the nice features Unity gives you?" you'd ask. Sure, let's talk about it.
Collision detection? In the world of 2D gaming, the math behind intersecting lines, circles, and rectangles is fairly straightforward, unless your game requires heavy-duty physics simulation.
Particle systems? In pixelart games, it's common to rely on handcrafted particle effects, crafted by artists and seamlessly integrated as animation frames.
Pathfinding? Classic algorithms like A* can be whipped up in a concise script of just about 50 lines of C#.
GUI? Depends a lot on the game, but many indie games don't really have a need for a really complex GUI. Plus if you already managed to abstract sprite drawing from the engine, building a basic GUI layer atop that is feasible.
The list goes on. Sometimes features indie developers might view as essential "engine offerings" can often be replicated with a pinch of creativity... often much easier than one might think. And if you make sure to keep that code well abstracted, you can keep reusing it on all of your future projects.
Godot 101: An Indie’s First Steps
For those new to Godot like I was, let's demystify some basics:
- Scenes & Nodes: Think of your Unity scenes filled with GameObjects. In Godot, it's all about scenes with Nodes, especially Node2D for 2D games. It's similar enough.
- The Most Important Methods: _Ready and _Process are Godot's best friends for Unity's Start and Update.
- 2D Sprites: Sprite2D class has you covered.
- Handling Input: Just tap into the _Input method.
- Audio: The AudioStreamPlayer is quite easy to use.
My main troubles were with procedural audio, which I use a lot, both for music synth playback and also randomized monster effects. While Unity’s OnAudioFilterRead is close to my heart, Godot offers something called AudioStreamGenerator. Though I hit some snags with it initially (more on this soon), it's handy for those looking for dynamic audio solutions.
Godot is promising, but it isn't perfect. My trials with AudioStreamGenerator in 4.1 are testament to that, I was simply not hearing any audio at all, which was frustating me a lot. Thankfully, this is where the power of the open-source community shines. With some sleuthing, I found a PR with the fix, built my custom Godot version, and voilà! My audio woes were history. For those fearful of building from source: it’s simpler than you’d think. Just give Godot’s documentation a go, they have good documentation that explains all steps necessary.
Is Godot the new Unity? Not quite... yet. It has its charms and advantages, like full source code access. But it also has some catching up to do. For instance, Godot's profiler doesn’t yet support C#, meaning third-party .NET profiling tools are a must. But despite its quirks, I can safely say Godot is well on its way to being a formidable choice for indie developers.
Also, I did observe some enhancements in performance. This can be attributed to Godot utilizing .NET 6, whereas Unity still uses an older version of Mono.
Transitioning from Unity to Godot was an enlightening journey, and I'm genuinely excited to see where Godot's future leads. While it may not replace Unity for everyone, it offers an exciting playground for indie developers willing to embrace something new. Here's to more experimentation and sharing in our vibrant indie community!
If you've resonated with my experiences, or are curious about the next chapter of Oni Hunters, I invite you to stay in the loop, follow me on Twitter. See you there!
This article first appeared on the author's Itch.io page. It has been republished here with their permission.