Maaack / Godot-Game-Template

Godot template with a main menu, options menus, pause menu, credits, scene loader, extra tools, and an example game scene.
MIT License
283 stars 17 forks source link

SceneLoader fails to load a cached scene (ResourceLoader.has_cached(scene_path) returns true, e.g. due to PackedScene being assigned to some node) #82

Closed hsandt closed 1 month ago

hsandt commented 1 month ago

After adding a custom script that was referencing some scene A in order to load it manually, I noticed that the main menu Play button stopped loading scene A as the initial scene.

Debugging SceneLoader.load_scene shows that the block checking if ResourceLoader.has_cached(scene_path): only sends a signal, then returns:

    if ResourceLoader.has_cached(scene_path):
        call_deferred("emit_signal", "scene_loaded")
        return

and in general you don't have custom code plugged to scene_loaded, so nothing more happens.

To fix this, I defined the following function:

func change_scene_to_path(scene_path: String) -> void:
    # Load scene from path
    # This should only be called for cached or very lightweight scenes
    # Otherwise, use load_scene to benefit from async loading
    var scene = ResourceLoader.load(scene_path, "PackedScene")
    var err = get_tree().change_scene_to_packed(scene)
    if err:
        push_error("failed to change scene to passed scene: %d" % err)
        get_tree().quit()

and added the following line before return:

change_scene_to_path.call_deferred(scene_path)

I added call_deferred to follow the logic of the existing line call_deferred("emit_signal", "scene_loaded") although it didn't seem necessary in this case, but always safer to change scene on deferred call anyway.

I suspect that the dev's intention was to mimic background loading, where we would emit a signal and let the user plug some custom behavior there. However, it seems unnecessary when the scene is already cached since it wouldn't take more than 1 frame.

So I should probably remove the scene_loaded signal which would be irrelevant when directly changing to new scene.

hsandt commented 1 month ago

Here is a commit on the game I'm currently working on, which contains the mentioned fix, as well as some changes in error messages: https://github.com/hsandt/lospec-jam-2-scaled-down-adventures/commit/007a7a1e2159c2794f84cc1f14c164a09193b260

Maaack commented 1 month ago

Thank you for catching this and sharing your fix.

I pushed a change that followed a similar convention to the _process() loop. I believe it fixes the issue, but I currently don't have a scene setup to test this case. Feel free to re-open if the bug persists, or if I've created a new one.