godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.84k stars 20.97k forks source link

Atlas texture region not resetting back to initial state when reload_current_scene() #97361

Open BurkusCat opened 1 week ago

BurkusCat commented 1 week ago

Tested versions

System information

Godot v4.3.stable.mono - Windows 10.0.22631 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1070 (NVIDIA; 32.0.15.6109) - AMD Ryzen 7 7800X3D 8-Core Processor (16 Threads)

Issue description

When using an atlas texture for a TextureRect, it is possible to set a "Region" for the texture to only display a portion of a spritesheet. This region can be set in the editor and then changed at runtime. When calling "reload_current_scene" (or switching to another packed scene and then ack again), the entire scene reloads except for the atlas texture. The atlas texture will stick on the last region it was set to during runtime.

Steps to reproduce

  1. Create a TextureRect. choose a new AtlasTexture as the texture and choose a region for it
  2. Advance the AtlasTexture to a different region at runtime
  3. Reload the scene

Expected The atlasTexture returns to its original region as defined in the editor

Actual The atlasTexture remains in its last runtime state until the game is fully restarted

How to use reproduction:

Minimal reproduction project (MRP)

GitHub repro: https://github.com/BurkusCat/reloadsceneatlastexture Zip repro: reloadsceneatlastexture.zip

AThousandShips commented 1 week ago

Resources are cached and won't be reloaded completely if they already exist in the cache, so any manual changes to them while loaded will remain if the resource isn't completely unused

However this depends on what is expected of reload_current_scene and if this is expected to completely reset all data in the scene or not when edited

But will take a look at what actually is going on here and this needs some analysis of what is causing this and if it is to be expected in general or how this could alternatively be handled, changing it might also break things if unexpected or if people rely on some resource having been modified

kleonc commented 1 week ago

Here's a possible workaround:

func _reload_scene_button_pressed():
    var scene_path: String = get_tree().current_scene.scene_file_path
    var scene: PackedScene = ResourceLoader.load(scene_path, "PackedScene", ResourceLoader.CACHE_MODE_IGNORE)
    get_tree().change_scene_to_packed(scene)
AThousandShips commented 1 week ago

Note that even if we consider the non-reloading of individual resources and not resetting change as unintentional or a bug changing how things work currently would slow down reloading as it would force reloading things instead of using the cache

One suggestion would be to add a boolean option to reload_current_scene to have it optionally ignore the cache, or document the above workaround

kleonc commented 1 week ago

Another (rather simpler) workaround would be to mark the given AtlasTexture as local_to_scene within the given scene, this way each scene instance will get its own copy of it (whether reloading the scene or creating multiple instances of it).

func _reload_scene_button_pressed():
    get_tree().reload_current_scene()

dXYrRijWeB

One suggestion would be to add a boolean option to reload_current_scene to have it optionally ignore the cache, or document the above workaround

So given it's already possible to mark specific Resources as local to scene I'm not sure if such additional option is really needed. Also marking as local to scene allows more granular control as it doesn't force not using cache for all Resources, so I'd consider it better / more flexible than such option.

BurkusCat commented 1 week ago

Marking the AtlasTextures as local_to_scene works for my main project and makes a lot of sense to me!