I'm aware of a few games that do this, although none made with Godot. With that said, yes, this is possible in Godot.
You will have a background Thread
, which goes down a list of data files to download, and downloading them.
With Godot, your first option for data files is pck files.
When you export a Godot game, Godot makes a pck file with all the Resource
s of the game... Godot loads and access this file using res://
paths.
You can create custom pck files from Godot using the PCKPacker
class. And you can load custom pck files in runtime with load_resource_pack
.
See also:
Beyond pck files, you have some other options:
- You can also work with Godot file formats. On that note, using the binary formats for release (i.e. don't use
.tres
use .res
, and don't use .tscn
use .scn
) will result in smaller file size.
- Addendum: Godot 4 can also save and load glb/gltf file in runtime using
GLTFDocument
.
- You can create your own formats. To add support to load them and saving them, create
an EditorPlugin
that installs custom ResourceFormatLoader
and ResourceFormatSaver
. Errata: The EditorPlugin
should not be necessary for this use case.
Whatever your data files are, you will make them available for download from the server. If it is a web server, your game can download them using HTTP client class.
A multiplayer server might be able to send serialized Resource
s (including scripts). But I'll remind you that you cannot send instances.
I'll also remind you that the res://
paths are a representation of the contents of the pck files. So you don't download into there (as a matter of fact, the res://
are not writable in release). Instead you download the data files into user://
paths, and load them from there.
By the way, you can have different data files for different platforms, different languages, or whatever criteria you deem appropriate.
As you can imagine, the player might want to interact with something that is not ready.
You can use the order of the data files in the list of the server to make that situation less likely.
But to actually deal with the incident, you want a module that loads scenes on demand... If the scene is not available, queue the appropriate data file for download instead... And wait (which might mean showing a "loading" screen). And the background Thread
should focus on whatever that module has queued.
I presume you don't want a "loading" screen...
Be aware that after downloading, the game needs to load the data files. And also loading and instancing the scenes takes time. So downloading the data files is not enough on its own to remove load times.
What you want is to load adjacent regions in a background process. And also unload distant regions.
See Background loading for Godot 4, or Background Interactive loading for Godot 3. You can use Area
(2D
/3D
) for load triggers.
And to be able to load adjacent regions, the game will first demand them from the module I described before. That will also result in in downloading the associated data files early.
And thus the situation where the player tries to interact with something that is not ready (where you need the "loading" screen) is even less likely... But we cannot completely rule it out. For example, in the case of a network disconnection... In a multiplayer game, you would have the player reconnect. But in a single player game, it would be a "loading" screen.
You would release the game with whatever the data files need to work. But if loading a data file requires loading another first, your games needs to know the order. So you would have to annotate it in the server.
I want to point out that a bit of duplication is acceptable. For example, if the common dependency is a few functions, it is not worth it to create a data file for them. Instead duplicate them in the data files that need them.
Finally, you might also want to incorporate updates and integrity checks. In fact, it is a good idea to do this in the first release to avoid future headaches.
So you annotate in the server the version of the data files, so the game can check if it has the latest one. And also annotate a hash of the data files. So the game can do the hash, and compare the result with the server, without downloading the data file.
You could also use binary diff patches for the data files... In this case, the client would download the diff to update instead of doing a full download. Which results in downloading less data for an update. Yet, this is beyond the question.