Bringing the game to real devices: exporting to Android, iOS, Windows, Linux, and macOS with export presets, platform-specific configuration and input, touch and orientation patterns for mobile, and managing package size and platform compliance.

All game systems are complete: animation, multiplayer, performance, plugins, and shaders. Episode 17 takes you out of the editor: exporting the game to real devices. Godot excels here — one codebase can reach Android, iOS, Windows, Linux, and macOS. But every platform has its own quirks: from configuration and input to app store rules.
This episode's roadmap: preparing export templates and presets, configuring per-platform presets, desktop export (Windows, Linux, macOS), mobile export (Android, iOS), input and orientation patterns for touch screens, then finishing with package size and platform compliance.
Before exporting, make sure export templates are installed — Godot runtimes specific to the target platform. In the Editor → Manage Export Templates menu, pick the version matching your editor, then click Download and Install. Without a template, the export button just shows an error message.
Next, create an export preset via Project → Export. A preset stores all of a platform's settings: target, permissions, icons, and compression. Save presets as .preset files inside the project so they can be version-controlled — the whole team and CI use the same settings. A single project can have many presets, for example android-release and android-debug.
Export can also be automated from the terminal — useful for CI:
godot --headless --export-release "android-release" build/game.apkEach preset has three parts you must understand:
Rendering choice also affects compatibility: the mobile and compatibility renderers are far lighter on low-end devices than forward_plus. For simple 2D games on phones, the compatibility renderer is often the safest choice.
Desktop export is the simplest: create a preset per OS, then export. Windows uses an .exe template, Linux produces a binary that can be wrapped in an AppImage or tar, and macOS produces a .app application that must be signed for wide distribution.
Some important notes:
.ico for Windows, multi-size .png for Linux, .icns for macOS. These differences are small but often slip through and make a game look unprofessional.user:// for user data and OS.get_environment for environment variables.Info
Don't wait until the end of the project to test exporting. Make a simple desktop build in the early episodes and export once a week — problems like missing icons, fonts, or paths are far cheaper to find early. "Only in the build" debugging is the most expensive kind.
Mobile requires extra preparation because the ecosystem processes are strict:
Install to device and make sure USB debugging is active. For release, you need a keystore (signing key) and must fill in the Keystore Config in the preset. You also need to set min_sdk and target_sdk according to the latest Google Play versions.Android and iOS both demand careful permission handling — only request permissions you actually use, because app stores scrutinize excessive permissions.
Desktop uses keyboard and mouse; mobile uses a touch screen. Luckily the Input Map system from episode 11 already unifies both: one action can be filled with both keyboard and touch input. For virtual touch controls, use the TouchScreenButton node or build your own UI buttons on screen.
For games needing analog controls like platformers or top-down shooters, a virtual joystick is far more comfortable than direction buttons. Build a simple joystick from two nodes: an outer circle as the touch area and an inner circle as the knob following the finger.
@export var radius_maks: float = 50.0
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventScreenTouch and event.pressed:
knob.global_position = event.position
elif event is InputEventScreenDrag:
var dari_pusat: Vector2 = event.position - pusat.global_position
knob.global_position = pusat.global_position + dari_pusat.limit_length(radius_maks)This pattern is important to master because real applications almost always need more than one simultaneous touch point — the player moves the joystick with the left thumb while pressing action buttons with the right thumb. Godot's Input Map handles multi-touch well as long as each virtual control uses a different action.
A common pattern for dragging the screen:
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventScreenDrag:
$Player.position += event.relative
elif event is InputEventScreenTouch and event.pressed:
$Player.position = event.positionOrientation also needs to be decided early: landscape for action games, portrait for casual games. Set it in the platform preset (Screen Orientation) and consider that locking orientation is cheaper than supporting dynamic rotation. On the performance side, target a stable 60 FPS, turn off unused features (heavy shaders, screen effects), and test with battery saver on — because thermals and battery are the enemies of mobile games.
Two final concerns before release: package size and compliance. Mobile games that are too big make users reluctant to download, and app stores set limits (Google Play caps at 200 MB for APK, with asset packs). Ways to reduce size:
Compliance concerns store rules: age ratings, privacy policies, consent for ads, and permission descriptions. For games that collect user data — including simple analytics — make sure there's a clear privacy policy and consent mechanism.
Warning
Binary size is only half the story; load time is also part of the experience. A small package loading uncompressed textures will still feel slow. Prioritize texture compression from the start, because changing the compression scheme later can alter your game's visual colors.
You can now bring the game to real devices: prepare version-controlled export templates and presets, export to Windows, Linux, macOS with their respective icon and signing settings, export to Android and iOS with keystores and Xcode, handle touch input and orientation for mobile, shrink package size with texture compression, and ensure platform compliance.
The key takeaways:
.preset so they can be version-controlled.compatibility or mobile renderers are safer for low-end devices than forward_plus.InputEventScreenDrag and TouchScreenButton for mobile.In episode 18, your game is ready to go anywhere — and that raises an architecture question: advanced architecture & patterns, from ECS-inspired patterns and entity management, systems decoupled with signals and messaging, to modular architecture and plugin-based scenes. Because big games don't win on features, but on foundations.