Skip to content

ResourceLoader.load() inconsistently ignores/replaces cache when loading PackedScenes #82830

@dandeliondino

Description

@dandeliondino

Godot version

4.1.1-stable, 4.2-dev6

System information

Windows 11

Issue description

I am working on a 2D game. Different levels are assigned to different environments (like overworld, underground, underwater). Most of the components are the same for each level, but the Sprite2Ds, AnimatedSprite2Ds and TileMaps all have slightly different artwork for each environment.

Instead of creating different versions of all the level components for every environment, I planned to swap the textures at runtime by using take_over_path() prior to loading each level.

However, this yielded inconsistent results, so I created this MRP to figure out what was happening.

There appear to be at least 3 inconsistencies:
(1) When the texture is assigned to a property that is not in a subresource, using ResourceLoader.load() with CACHE_MODE_REPLACE does not change textures already on-screen. When the texture is in a subresource, it will.
(2) If the texture is in a subresource and its node is nested inside a saved branch of the scene being instantiated, it won't ignore or replace the cache. If the texture is not in a subresource, it will.
(3) When the node is an AnimatedSprite2D and its SpriteFrames resource is saved externally, it won't ignore or replace the cache. When the node is a TileMap and the TileSet resource is saved externally, it will ignore or replace the cache.

I don't see other issues describing exactly the same things for Godot 4, but #59669 might be related. And, while #59686 and #62408 are for Godot 3.x, the root cause (the cache parameter not being passed consistently to other functions) seems like it could be relevant here.

I obtained the same results with Godot 4.1.1-stable and Godot 4.2-dev6, and in with both Compatibility and the Forward+ renderers.

Steps to reproduce

This project contains a script that instantiates Sprite2Ds, AnimatedSprite2Ds and TileMaps before and after using take_over_path() to swap their shared texture "frog.png" with "snail.png". For the Sprite2D, the texture is assigned to the texture property. For AnimatedSprite2D and TileMap, the texture is assigned inside of its subresource.

The script on main.tscn has the following options:

options

"Instantiate after only" does not instantiate any scenes until after take_over_path() is called (preventing "frog.png" from being cached).

"Scene types" are described below.

"Cache mode" is the CacheMode enum value passed to ResourceLoader.load().

"Repeat swap" swaps back and forth between the textures in an infinite loop. The results are consistent with the first swap, so they are not shown here.

Scene types:

Root scenes - the node is the root node.

root_scene

Child scenes - the node is not the root node. Child scenes always behaved the same as Root scenes, so their results aren't shown separately.

child_scene

Nested scenes - the node is a saved branch.

nested_scene

External resources - the node is the root node and references a resource that is saved externally (not relevant for Sprite2D).

external_resource

Root/Child Scene results

root_replace

root_ignore

root_reuse

"Instantiate after only"

instantiate_after_root_replace

instantiate_after_root_reuse

Nested scene results

nested_replace

nested_ignore

"Instantiate after only"

instantiate_after_nested_replace

External resource results

external_replace

external_ignore

"Instantiate after only"

instantiate_after_external_replace

Edit 10/7/2023: Added a separate screenshot for cache mode ignore in nested scenes.

Minimal reproduction project

take_over_path.zip

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions