Godot Porting Guide

Background and Goals

Note: This post is a work in progress. Please let me know if you have experience or expertise to share!

I helped port Keep Talking and Nobody Explodes to 8 platform targets with 6 optional VR APIs and multiple storefronts with different services. We did this with the Unity game engine from a single main branch in source control. Through this process, I learned a little about what needs to be done to port and maintain a game on so many platforms.

This guide enumerates some general porting challenges that come up, regardless of which game engine is used, and describes how to solve each of them using the Godot game engine. In cases where there is currently no built-in solution, I have provided a link to proposals where there is discussion on the subject.

This article was last updated for Godot version 4.3.

Controlling App Size and Memory Usage:

Controlling Behaviour:


Controlling App Size and Memory Usage

Bulk Changing Import Parameters

During the porting process, you will likely want to apply specific import parameters to a large number of resources all at once. These two tools in the Godot editor help with this process:

  1. Multi-editing import parameters
  2. Changing default import parameters

When multi-editing import parameters for a large number of files in different folders, it may be tedious to select files with the default File System dock. To make this a lot easier, use these steps:

  1. Switch to the split view using the icon on the top right of the File System dock
  2. Filter files to match the file extension of the files you want to multi-edit, such as “.png” for all png texture files

When changing default import parameters, only newly imported resources will use these defaults. You can use the “Preset” button to apply these default parameters to all existing resources selected in the File System dock.

Texture Resolution

One of the best ways to reduce app size and memory usage on mobile devices is to reduce the texture resolution for these exports. This change should not impact existing PC exports that use higher resolution textures. Additionally, you may desire higher resolution textures for high performance Android VR platforms such as Meta Quest, while using lower resolution textures for Android devices that download your game from an app store such as Google Play.

There is currently no built-in functionality in Godot 4 for this. Discussion here.

To work around this, custom scripting or a custom engine build can be used to generate new resources at export time by changing the Texture2D Size Limit import parameter. Note that this Size Limit parameter will impact the size of Sprite2D nodes, etc.

Audio Compression

Similar to controlling texture resolution, app size and memory usage can be reduced on mobile exports by changing the audio compression settings. This change should not impact existing PC exports that use higher audio.

There is currently no built-in functionality in Godot 4 for this. Discussion here and here.

For now, my recommendation is to simply use the same audio compression across all exports, but it is also possible to use custom scripting or a custom engine build to remap audio files at export time.

Selectively Excluding Resources

Textures for one export should not be included in other exports that cannot use them to keep the app size small. For example, textures specific to the Meta Quest export should not be included in the Google Play export.

I recommend the “Export all resources in the project except resources checked below” mode instead of the options that automatically detect dependencies because the later will not automatically add new scenes or resources if the new resource cannot be detected as a dependency, such as a scene that is loaded through a script by its path. If a new scene or resource is not added to each and every export preset, a runtime error will occur and can only be seen on the export(s) that are missing the new resource.

Controlling Behaviour

Project Settings

Each export can use different project settings by creating project setting overrides for specific feature tags. You can either use built-in feature tags, such as “pc” or “mobile”, or create your own feature tags, such as “google_play” or “meta_quest”.

The first override that matches a feature tag of your export will be used. If no override matches any of your export’s feature tags, the base project setting will be used.

Packed Scenes and Other Resources

Packed scenes can be used to encapsulate export-specific behaviour, visuals, and audio. For example, a packed scene could contain a localized diagram of game controls when using an Xbox controller. This packed scene should be shown on platforms such as Windows, Linux, and Xbox, but a different packed scene should be shown on other platforms.

Simple scripts can be written to swap packed scenes using feature tags:

var controller_diagram_scene: Resource

func _init() -> void:
  if OS.has_feature("nintendo_switch_controller"):
    controller_diagram_scene = load("res://switch.tscn")
    controller_diagram_scene = load("res://xbox.tscn")

func _ready() -> void:
  var instance = controller_diagram_scene.instantiate()

Important note: Only built-in feature tags are available when running a project or scene from the editor! To test with custom feature tags, you must export the project.

It may be valuable to remap other types of resources based on an export’s feature tags. For example, instead of encapsulating visuals in a packed scene, you may want to simply remap button callout textures or materials. This may be done through scripting with custom feature tags in a similar way to the above.

There is currently no built-in functionality for remapping resources in different exports. Discussion here.

Scripting: Platform Services and Capabilities

Custom feature tags, configured per-export, can be used to change behaviour.

For example, if your game supports leaderboards on Meta Quest and does not support them on Google Play, you can assign a “leaderboards” feature tag to the Meta Quest Export and check for it in your code:

if OS.has_feature("leaderboards"):
  pass # make leaderboards visible here
  pass # make leaderboards invisible here


Inspect Build for Resource Sizes

When reducing the app size of an export, one of the most valuable things to know is the file size of each resource in your app package. Specifically, you want to know which are the worst contributors to an app size that is too large.

For each export preset in your project, select “Export PCK/ZIP…”, choose the .zip file extension, and extract the resulting zip file into a folder on your computer. Then use a file size analysis tool to determine which resources are taking up too much space in your build. This is an approximate method because final game package compression prevents knowing exactly how much any individual resource may be contributing to your app size without the tedious process of exporting a build with an without each specific resource.

I like to use WizTree on Windows, and there are many other tools like it for other platforms:

Quickly Preview Exported Resources

Especially when modifying import settings of a resource to reduce its file size in the final app, it can be useful to inspect what that resource will look or sound like without running the game.

The Godot editor currently allows for viewing the host platform’s imported texture at its largest mipmap level in the Inspector panel by double clicking the texture in the File System panel. I am not aware of any tooling that allows for this sort of functionality for other textures formats or resources. Please let me know if you know of any!

Quickly Debug on Target Platform

After porting your game, it is normal for the game’s behaviour to be different between exports. These differences make it important to be able to debug export-specific scripting issues by stepping through scripts with a scripting debugger attached.

You can do this using remote debugging and one-click deploy.