Performance, Battery, and Getting on the Store
Module 7 ยท Lesson 3 ยท ~40 min ยท pre-launch checklist
Your game runs beautifully on your dev phone. That's because your dev phone is a $900 flagship with a cool case and a clean battery. The median Android device out there is a 3-year-old phone with half a battery charge, thermal throttling, and 20 other apps fighting for memory. This lesson is the "make it actually ship" pass.
Profiling in Godot
Two built-in panels:
- Debugger โ Profiler โ per-frame CPU breakdown by function. Start it, play for 30s, stop. The hot list shows where your frame budget goes.
- Debugger โ Visual Profiler โ GPU breakdown. Shows how long each pass (canvas items, lights, post) takes.
You want each frame <16.6ms (60fps) or <33ms (30fps, fine for a turn-based game). Over budget and the game janks.
Common mobile bottlenecks
- Too many nodes. A scene with 5000 nodes will lag on a mid-tier phone. Check with
print(get_tree().get_node_count()). For Lexicon Duel you should be well under 200 during a duel โ if not, something's leaking.
- Fill rate on particles. A GPUParticles2D spewing 500 big transparent sprites over the whole screen shreds the fragment shader. Keep particle counts modest (<100 per emitter), keep them small.
- Unnecessary
_process. Every node with a _process override wakes up every frame. Kill them when not needed: set_process(false). Prefer event-driven (signals) over polling.
- Font rendering. Using 10 different font sizes causes 10 texture atlas bakes. Pick 3 sizes, reuse.
- Large textures. Import an 8192ร8192 background for a phone screen and you've wasted 256MB of GPU memory. Import Settings โ Mipmaps on, clamp max size to what you actually need.
Battery life
Turn-based games should be gentle on batteries. Checklist:
- Low-processor mode. When the UI is idle (menu, paused), call
OS.low_processor_usage_mode = true. This caps the frame rate and lets the CPU idle. Re-enable animations by setting it back to false during duels.
- Cap the frame rate. Project Settings โ Display โ Window โ V-Sync Mode: Enabled. Or explicitly
Engine.max_fps = 60.
- Don't burn cycles in menus. A title screen at 60fps running an animated background at full tilt drains battery while the player reads the menu. Ease off.
- Screen brightness isn't your problem. It's the dominant battery cost of a mobile game, but it's the user's setting. Don't fight it.
# Global autoload โ toggle when entering/leaving menus
func enter_idle() -> void:
OS.low_processor_usage_mode = true
Engine.max_fps = 30
func enter_duel() -> void:
OS.low_processor_usage_mode = false
Engine.max_fps = 60
APK size
Your debug APK is probably 60-80MB โ acceptable. At 150MB+ you start losing Play Store installs. Culprits:
- Export templates include everything. Project โ Export โ Features โ uncheck features you don't use (e.g. XR, Mono, WebP if you use PNG). Use the arm64-v8a filter โ don't ship x86, almost nothing modern uses it.
- Uncompressed audio. WAV is uncompressed. Convert ambient/music to OGG. Short SFX can stay WAV.
- High-res art for a phone. A 2048ร2048 card face that renders at 256ร256 is wasted.
- Leftover test scenes. The export includes everything in your
res:// by default. Either delete scratch files or set "Filters to exclude" in the preset (test_*.tscn, scratch/**).
Signing for release
Debug keystore is for you. Release keystore is what the Play Store uses to identify this game as yours, forever. If you lose it, you lose the ability to update your app. Treat it like a master password.
keytool -v -genkey -keystore lexicon-duel-release.keystore \
-alias lexicon-duel -keyalg RSA -keysize 2048 -validity 10000
It'll prompt for a password (use a strong one, save to a password manager), and some metadata (your name, org, country). Store the resulting .keystore file in a safe place โ not in git. Backup to iCloud/Drive, and to an external drive. Two copies minimum.
In Godot: create a second preset "Android Release," same settings as debug but:
- Uncheck "Debug"
- Point "Release Keystore" at your release keystore
- Enter release user/password
- Export filename:
build/lexicon-duel-release.apk (or .aab for Play Store โ see below)
APK vs AAB
The Play Store wants AAB (Android App Bundle), not APK. An AAB is a container the Play Store splits per-device to reduce download size. Same Godot preset, just toggle the "Gradle Build" + "Export Format: AAB" in the preset options.
APKs are still useful: for sideloading to friends' phones, for itch.io distribution, for ad-hoc testing. Maintain both presets.
The Play Console onboarding
This is where the weeks-long wait actually lives. Realistic timeline for a first-time publisher as of 2026:
- Google Play Console account: one-time $25 fee. Sign up at play.google.com/console.
- Identity verification: must provide real name, address, government ID. 2โ14 days to verify.
- 20-tester closed test requirement: Google requires you to run a closed test with 20 active testers for 14+ days before your production listing unlocks. This is the part new devs don't see coming. Recruit 20 testers early.
- Content rating questionnaire, privacy policy URL, data-safety disclosure, target API level. All forms. Budget a full afternoon.
Reality check
From "I have a done game" to "on Play Store public listing" is realistically 4-6 weeks for a first-timer. Not because the game needs work โ because of Google's tester rule and review queues. Start the Play Console track as soon as you have an MVP, in parallel with polish.
Pre-launch checklist
Run through this before submitting:
- โ Game runs on a 3-year-old $200 Android without jank
- โ Game survives device rotation (if you support it) and backgrounding
- โ Game doesn't crash on "low memory" โ test by opening 10 other apps first
- โ Saves persist across force-close
- โ No dev builds, no placeholder art, no "TODO" strings, no debug logs in release
- โ Icon, screenshots (phone + tablet), feature graphic, short + long description all drafted
- โ Privacy policy page published (free host: GitHub Pages, Netlify)
- โ Data safety form filled honestly (if you collect nothing, say so โ easier approvals)
- โ Target API matches Google's current requirement (they bump annually)
- โ 20 testers lined up for closed test
Do this now
- Run the Godot profiler during a duel. Note any frame over 20ms.
- Check
get_node_count() in your root scene during a duel.
- Measure the current debug APK size. If over 80MB, hunt the fat.
- Generate the release keystore. Back it up. Back it up again.
- If you're serious about shipping: start a Play Console account today, so the verification is happening in the background while you polish.