People ask us fairly often what an Android game development company actually runs under the hood, expecting a single tidy answer like "Unity, obviously." The real answer is messier and depends entirely on the game. An idle clicker with simple 2D sprites and a hypercasual physics puzzler have almost nothing in common technically, even though both ship as "Android games." Here's what our stack actually looks like across different project types, and the reasoning behind each choice.
Native (Kotlin) vs. Engine: The First Real Decision
The first fork in the road isn't which engine to use, it's whether to use an engine at all. For simple 2D games with light physics, we sometimes build directly on Android's Canvas API with Kotlin, using SurfaceView or a custom View with a game loop running on its own thread. This sounds old-school, but it gives full control over rendering and avoids shipping a 100MB+ engine runtime for a game that's fundamentally a few sprites and touch input. The tradeoff is real, though: no built-in physics, no scene editor, and every animation system gets hand-rolled. We only go this route when APK size and startup time matter more than development speed, which is a smaller slice of projects than people assume.
Unity: Still the Default for Most Projects
For anything with real physics, particle effects, or cross-platform ambitions beyond Android, Unity remains our default. Unity's 2D toolset (Tilemap, 2D physics, Sprite Shape) covers most casual and mid-core game requirements without custom tooling, and its Android build pipeline is mature enough that we're not fighting the toolchain on every release. The C# workflow also means our engineering team isn't context-switching between a native Android codebase and a separate game codebase when a project needs both a game and companion app features, like a shared login or in-app purchase flow.
The real cost of Unity isn't licensing, it's APK size and cold-start time. A bare Unity build adds meaningful overhead before a single game asset loads, which matters on the lower-end devices that still make up a large share of the Android install base globally. We spend real engineering time on IL2CPP stripping, texture compression settings (ASTC over ETC2 where device support allows), and asset bundle splitting specifically to claw that back.
LibGDX: When We Want Java/Kotlin Without Losing Engine Convenience
LibGDX sits in an interesting middle ground we reach for more than most teams expect. It gives us Box2D physics, a scene graph, and cross-platform builds while keeping the codebase in Java or Kotlin instead of C#. For teams that are already deep in Android-native tooling and don't need Unity's editor-driven workflow, this cuts down the mental overhead of maintaining two separate skill sets across a team. It's a smaller community than Unity's, so we rely more on reading engine source directly when something breaks, but for 2D-focused, performance-sensitive titles it consistently produces smaller, faster builds.
Physics and Performance Tuning
Box2D shows up across almost every engine choice we make, either built in (LibGDX) or as a plugin (Unity). Getting physics to feel right on Android specifically means tuning for variable frame timing, since Android's frame pacing across different OEM skins and refresh rates is far less consistent than iOS. We profile heavily on mid-range devices, not flagships, because that's where jank actually shows up first. A game that feels smooth on a Pixel and stutters on a budget Samsung device isn't ready to ship, and that gap is easy to miss if your test devices skew premium.
Flagship (16.6ms budget) |███████████████████████████████████░░| ~92% frames on time
Mid-range (16.6ms budget) |████████████████████████░░░░░░░░░░░░| ~68% frames on time (untuned build)
Mid-range (16.6ms budget) |███████████████████████████████░░░░░| ~85% frames on time (after tuning)
Budget (16.6ms budget) |██████████████████░░░░░░░░░░░░░░░░░░| ~52% frames on time (untuned build)
Backend: Firebase Is the Default, PlayFab for Live-Service Titles
Firebase covers the majority of our backend needs, crash reporting, remote config for live-tuning difficulty or drop rates, and A/B testing without a store update. For titles with real live-service ambitions, leaderboards, matchmaking, virtual economies, we bring in PlayFab instead, since building that infrastructure from scratch on Firebase alone means reimplementing things PlayFab already handles well. The decision usually comes down early in production, since retrofitting live-service backend architecture onto a game that launched without it is a much bigger lift than planning for it from day one.
CI/CD: Automated Builds Matter More Than People Expect
We run Fastlane-driven CI/CD for Android builds, automating signing, versioning, and Play Console uploads to internal testing tracks on every merge to a release branch. This matters more for games than typical apps because game builds are heavier and slower to compile, and manual build-and-upload cycles eat real hours across a project timeline. Automated builds also make it realistic to actually test on a device farm regularly instead of only right before a release, which catches device-specific rendering bugs earlier when they're cheaper to fix.
Monetization SDKs and the Integration Tax
Ad mediation (AdMob with mediation layers for Unity Ads, AppLovin, etc.) and IAP billing libraries are usually the least glamorous and most bug-prone part of the stack. Every SDK added increases APK size, adds another thing that can break on OS updates, and adds another dependency to keep current. We keep a hard rule of vetting SDK necessity before integration, since it's common to see hypercasual projects accumulate five ad networks "for fill rate" that could realistically be trimmed to two without meaningfully hurting revenue.
What This Actually Means for Choosing a Stack
None of these tools are inherently better than the others; they solve different problems. The mistake we see most often, both in our own early projects and when reviewing other teams' codebases, is picking a stack based on familiarity rather than the actual constraints of the game, target devices, and team skill set. An Android game development company that standardizes its stack per project type, rather than defaulting to one engine for everything, ends up with more predictable timelines and fewer late-stage performance surprises. If you're scoping a new Android game and are unsure which of these fits, happy to talk through the tradeoffs in the comments.
Top comments (0)