GDevelop icon indicating copy to clipboard operation
GDevelop copied to clipboard

Unload scene specific resources on demand

Open ViktorVovk opened this issue 10 months ago • 2 comments

This is an implementation of functionality for unloading all resources from the scene we are leaving. For example, we have several scenes (Preloader, postPreloader) that contain a significant number of resources such as images, audio, spine animations, atlases, JSON files, and so on. After these scenes have been loaded, once we transition to the so-called main scene, we want to remove (unload) all resources from the scenes that we do not expect to return to during the game’s runtime.

Plan for implementing the unloading of scene-specific resources on the GDevelop side:

  1. An additional boolean parameter needs to be added to the "change scene" action. Enabling this parameter will indicate that all resources specific to the scene being exited should be unloaded. It is assumed that we will not return to this scene during the game’s runtime.

  2. During the execution of the "change scene" action, the _destroy method is eventually called on the scene object (in runtimescene.ts). At that point, the resource cleanup method disposeScene—implemented in the ResourceLoader class—is invoked.

  3. The disposeScene method accepts the scene name as a parameter and creates a Map where the keys are resource types (ResourceKind) and the values are arrays of ResourceData.

  4. In the ResourceLoader class, there is a field _resourceManagersMap where the keys are resource types (ResourceKind) and the values are resource managers. This makes it easy to correlate this map with the map of resources grouped by type since they share the same keys.

  5. In each resource manager class, a method disposeByResourcesList has been implemented, which takes an array of resources that need to be cleared. This method performs the cleanup of the resources in the provided list.

ViktorVovk avatar Feb 07 '25 11:02 ViktorVovk

Hi @ViktorVovk! Main feedback is that we think the parameter to choose if a scene resources should be unloaded when the scene is left should be a property of the scene, instead of being a parameter of the action. I.e: something that would be stored on the scene (in Layout.h, and serialized into the JSON, so you could read it ).

(we could imagine an action to change this at runtime, but in most cases it could be something that never changes).

The unloading algorithm could unload resources that are neither from a living scene (including the next one) nor a scene with the "unload" property disabled.

Let's discuss what this would imply and how this would impact the algorithm that unloads resources :)

4ian avatar Mar 20 '25 23:03 4ian

Hi @4ian. Thank you for taking the time to review this PR. I agree with your comment regarding where the need to unload resources from the scene we’re leaving should be specified. I’ve done some refactoring and moved this parameter into the scene’s properties. By default, this parameter is set to false.

I would really appreciate it if you could take another look at this PR. Best regards.

ViktorVovk avatar Mar 25 '25 13:03 ViktorVovk

I've done multiple changes to this PR. The main advantages are:

  • No new functions to trigger loading of scenes, the existing ones are used :)
  • The unloading is now "safe": it will only unload resources that are used in the scene being unloaded and not the resources loaded for other scenes.
  • The unloading is now "not permanent" and so also safe if you go back to the scene later: the scene will simply be considered as "not loaded" and it will trigger a loading of the missing resources.
  • The unloading is only done if it's the only scene with this name in the stack (so again, it's safe).
  • The unloading is "avoiding useless work": if you switch from a scene that is unloaded to another, it won't unload and then reload the resources shared by the unloaded scene and the new one.

Internally I refactored the list of scenes status (so we can track if they are not loaded, loaded or ready). I've added some tests (a bit hard to read, but will hopefully catch any regressions in the future).

I'm keeping track here of what I would like to finish before merging this so it's officially supported:

  • [x] Rename disposeByResourcesList to unloadResourcesList (just a naming issue, I prefer to keep the name dispose for when something is deleted and can't be reused. Here the resources could be reloaded later)

I still want to do also some additions:

  • [x] Add a property on scenes to avoid disable the pre-loading of their resources at startup. In an extreme case, someone could disable the pre-loading of all scenes, meaning only the first scene would be loaded.
  • [ ] Ensure that when a scene is unloaded, when another scene is loaded, then it's not reloaded again. It's a bit of a edge case but if you unload a scene it's fine, but if you unload another one and then load it again, it will also load the first scene that was unloaded. So I will probably add a status "unloaded" which is a way to say "hey, I was unloaded, please don't try to reload me UNLESS it's needed".
  • [x] Add a test game I started to GDJS/tests/games

From what I've tested in my test game, this should allow scenes to be safely unloaded, and in case the player/game navigates back to an unloaded scene, resources will be loaded again. And there is in theory no risk at all to unload a resource used by another scene. So I'm hopeful this will be more than enough, and big games can unload scenes if they can by just toggling a checkbox and not worrying about the rest 👍

4ian avatar Jun 27 '25 17:06 4ian