You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
"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.
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.
Nested scenes - the node is a saved branch.
External resources - the node is the root node and references a resource that is saved externally (not relevant for Sprite2D).
Root/Child Scene results
"Instantiate after only"
Nested scene results
"Instantiate after only"
External resource results
"Instantiate after only"
Edit 10/7/2023: Added a separate screenshot for cache mode ignore in nested scenes.
- Unify documentation, hoping to clear misconcepctions about about propagation of the cache mode across dependant loads.
- Clarify in docs that `CACHE_MODE_REPLACE` now also works on the main resource (from godotengine#87008).
- Add two recursive modes, counterparts of `CACHE_MODE_REPLACE` and `CACHE_MODE_IGNORE`, since it seems some need them (see godotengine#59669, godotengine#82830).
- Let resources, even loaded with one of the ignore-cache modes, get a path, which is useful for tools.
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:
"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.
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.
Nested scenes - the node is a saved branch.
External resources - the node is the root node and references a resource that is saved externally (not relevant for Sprite2D).
Root/Child Scene results
"Instantiate after only"
Nested scene results
"Instantiate after only"
External resource results
"Instantiate after only"
Edit 10/7/2023: Added a separate screenshot for cache mode ignore in nested scenes.
Minimal reproduction project
take_over_path.zip
The text was updated successfully, but these errors were encountered: