After releasing my first mobile game ( Bitey Trees ) exclusively on the iPhone App Store last September, I set my sights on my next game development goal: Building and releasing a cross-platform mobile game, for both iOS and Android. It’s still in the very early phases right now – I’ve been taking my sweet time getting started with it and trying to plan things out – but for this blog post, I wanted to share my preliminary experiences with building for both platforms using Godot Engine, the game engine I’ve decided to use for this project.
From the beginning, my plan for getting started on this next game had two parts, which I’d planned to work on simultaneously: (1) bootstrapping a skeleton for the game in Godot Engine, including figuring out a lot of those tricky little things like building for different mobile devices or creating a save system, and (2) designing the actual gameplay and mechanics “on paper” as much as possible, so that I have a clearer road map to work from when it comes to actually developing it. And the number one item on my “bootstrapping” to-do list was to successfully build to both an iOS and Android device.
I’m not sure if that might sound a bit backward from how most people would work… But over the past few years, one of my big takeaways from playing around with iOS game development has been that trying something out on a real device beats trying it out in a simulator — being able to see how things really look as you hold it in your hand, and use the actual touch controls, is an entirely different experience than clicking around a computer screen with a mouse. So it was important to me to be able to build to the actual physical devices I was targeting from the very start of this project.
Building for Android
One big challenge with building for a real physical Android device, though, was that I’d been an iPhone user for many years, and didn’t even actually own an Android device. I’d flirted with the idea of buying one just to play with, but for a long time that seemed like it would be a ridiculous frivolous expense (since I had no intention of actually fully switching over from my iPhone).
But then one day, I was in a Best Buy store and saw an Android phone for $29, and decided kind of impulsively to just go ahead and buy it. It was nothing fancy by any stretch (a Moto E5 with 16 GB of storage and locked to a specific carrier if I ever wanted to activate it for cellular use) but even a super low end device seemed like it should be suitable enough for my purposes.
Since I’d never attempted to do any kind of Android development before, I started out by just trying to deploy a simple native Android app to this new phone, rather than jumping straight to trying to build from Godot Engine. For this I downloaded Android Studio and followed the “Build Your First App” tutorial, including the delightful little arcane ritual where you need to go into a settings menu and tap on a version number seven times in order for the phone to declare you a developer, and then successfully deployed a very simple “Hello World” app to my new phone.
Once I’d finished that, I switched over to the Godot Engine documentation on exporting for Android. This is pretty thorough, but I got to gloss over most of the stuff at the beginning since I’d unwittingly made it much easier for myself by playing around with Android Studio first. I was actually pleasantly surprised by how smoothly the process went, and by the fact that there’s even a button right there in the editor to run your game on Android:
Overall, I couldn’t have been happier with how things went, and that my crazy scheme with the ultra cheap low-end Android device worked like a charm. How would the iOS export process compare?
Building for iOS
It’s safe to say that I’ve had much more experience with iOS development at this point, but for the most part it’s been native iOS directly in Xcode using Swift. So I wasn’t really sure how tricky or time-consuming it would be to build to an iOS device from Godot Engine.
Fortunately, Godot Engine’s documentation on exporting for iOS is also pretty solid, and I didn’t have any issues following the steps to get it set up (though I’m not sure if my previous experience with iOS might’ve made it a bit easier). But the basic process is clicking an “export” button in Godot Engine, and then opening and running from Xcode like you would with any other iOS project:
I was actually so satisfied with how smoothly this went that I didn’t even bother with the next few steps to link the Godot Engine files so that you don’t need to re-export the iOS build after making changes in Godot Engine. (I will likely revisit this in the future if I’m ever at a point where I need to quickly and repeatedly test things out specifically on iOS, but in the meantime, I have that handy little Android button right there in the Godot Engine editor for easily testing things on an actual physical device.)
The Engine-Questioning Pit of Despair
After successfully putting that simple Godot Engine game on both an Android and iOS device, I felt like it was a solved problem, and moved on to other tasks – including other things in Godot Engine like figuring out how to best handle scene transitions and audio, but also working on the design of the game I wanted to make, mostly in Google Docs or Inkscape. (For anyone curious, here is some concept art I posted on Twitter about one aspect of the game design I’ve been considering.)
But then a few weeks ago, shortly after Godot Engine 3.2 was released (and I excitedly downloaded it to check it out), I tried the Android button again only to realize that it didn’t work anymore – the phone just kind of sat there with a blank screen rather than ever displaying the game. So I tried running it on one of my iOS devices instead, only to find that that was broken too, failing with some cryptic build error.
At the time, this felt like a huge setback – maybe because the project is still in such an early phase, without anything resembling real gameplay yet, and because I’m doing all of this game development stuff purely as a hobby in whatever little time I can find after my various real-life responsibilities (working full time, married with two kids). For a few days, I just kind of wallowed in a pit of despair rather than doing anything to try to troubleshoot or fix the issues, and during this time I even considered abandoning Godot Engine entirely.
After all, at this point I’ve gotten the distinct impression that many developers consider cross-platform mobile development to be sort of a pipe dream – something that sounds great in theory, and maybe works fine in the simplest cases, but also comes with so many headaches and limitations that you’d almost be better off developing separate, native apps for iOS and Android. (And my one very brief experience with React Native during a hackathon seemed to basically confirm this.) Maybe mobile games were no exception – maybe I would be better off sticking with SpriteKit for iOS, and figuring out some native solution for Android.
On the other hand, if I had any interest in releasing a cross-platform mobile game in the next decade, leveraging an open-source tool being actively built by a huge community of contributors seemed like it would probably be my best shot… So I decided to buckle down and see if I could get the issues resolved. And they actually turned out to be stupidly simple to fix:
- iOS - This turned out to be due to the armv7 architecture being enabled in my project’s settings (which I assume was a default previously?) despite being slowly obsoleted by Apple and apparently no longer supported in Godot 3.2. Unchecking one little checkbox fixed the iOS build.
- Android - This appeared to be due to using GLES3 instead of GLES2 - I don’t have a clear link on whether a default changed in Godot 3.2 or if I may have messed up a setting somehow somewhere along the line, but in any case switching it in my project resolved the issue.
It was a relief to have things working again… But more importantly, I think that brief experience really got me thinking about one very important aspect of this next game project, and lead to an important decision.
Decision Point: Godot Engine, All The Way
With my first game, I decided very (very) early on to use SpriteKit. The lack of cross-platform support wasn’t much of a concern to me at the time – I was a complete beginner at this, so I figured I would focus on releasing a game on one platform, and then depending on how it went, I could look into expanding to other platforms in the future. And that was it – the decision was made. There wasn’t ever even the possibility of switching to something else, so for any challenge that came up, the only question was “how do I accomplish XYZ in SpriteKit?”
That may sound like a debilitating limitation, but it’s actually very liberating in a way. The biggest challenge for a hobbyist game developer, I think, is actually keeping up the momentum to finish a project – and nothing kills momentum on a project faster than the looming possibility of scrapping everything to start over from scratch with a different engine. And the temptation of switching to a different engine will always be there, no matter which engine you choose, because the grass is always greener on the other side.
So for this next game, the decision is made from here on out: It will be made with Godot Engine. And for any challenge that comes up, I will either figure out a solution, drop the feature in question, or (and this is an amazing possibility that wasn’t available to me when working with SpriteKit) modify the very source code of the engine itself and submit a pull request.
So anyway, that’s the story of my experience so far playing around with Godot Engine for cross-platform mobile game development. I’m excited to be embarking on this project, and am looking forward to getting to the point where it starts to come together as a real playable game – which I’m sure will be the subject of many future dev blog posts!
For anyone who’d like to follow along with the latest updates, feel free to follow me on Twitter, subscribe to the blog’s RSS feed, or sign up for the email mailing list (only used for important updates). Thanks for reading!