godotengine / godot

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

Some resources will randomly reset their UID #62258

Closed KoBeWi closed 1 year ago

KoBeWi commented 2 years ago

Godot version

0aa85f4

System information

Windows 10 x64

Issue description

Example diff:

diff --git a/default_bus_layout.tres b/default_bus_layout.tres
index 8cf0b3a7..f306fb8d 100644
--- a/default_bus_layout.tres
+++ b/default_bus_layout.tres
@@ -1,4 +1,4 @@
-[gd_resource type="AudioBusLayout" load_steps=2 format=3 uid="uid://mebhjwywmmgu"]
+[gd_resource type="AudioBusLayout" load_steps=2 format=3 uid="uid://bn3ouxpvseinh"]

There is new UID every time I load the project. No idea what causes this, as I wasn't able to reproduce in minimal project.

Steps to reproduce

  1. Create default_bus_layout.tres
  2. Restart the project
  3. The bus layout now has a different UID if your project is unlucky to trigger this :/

Minimal reproduction project

No response

Maran23 commented 2 years ago

I think this can happen for every .tres file, so also custom ones for e.g. saving/loading data (Savegame).

Zylann commented 2 years ago

I have seen this happen with tscn files as well. To me the entire point of UIDs is them not changing. To the point they are used exclusively in engines like Unity to identify assets, even across projects (useful for plugins and asset packs!). If they change, they instantly loose most of their usefulness, and rather become a nuisance.

TokisanGames commented 2 years ago

The ticket should be renamed to something like 'UIDs change too frequently,' as it's not just limited to the audio busses. It constantly happens to my theme, and all other scene and resource files. Git picks up the meaningless changes every day.

Original PR https://github.com/godotengine/godot/pull/50786

@Calinou Can this be added to the GD4 roadmap please? Maybe needs a regression tag? It's not just Audio (tag).

KoBeWi commented 2 years ago

I think the reason why this happens is that default bus layout is leaded very early in the project and UIDs might be unavailable then. I can confirm that it also happens with other resources, but only bus layout is consistently affected.

EDIT: I checked and the resource is loaded with correct UID. Or at least the UID is available, so either it's lost or not loaded properly into the Resource object.

TokisanGames commented 2 years ago

This isn't completely fixed. In beta 3, it appears default_bus_layout.tres is fixed, but my theme.tres and scene files and potentially every other tres are still changing subresource UIDs nearly every time they are run/saved.

-[sub_resource type="Image" id="Image_cbjwt"]
+[sub_resource type="Image" id="Image_k4fhf"]

Edit: Yes, it impacts my text materials as well. Safe to assume it's all resources. It also affects anything that references the changed subresource. Eg.

image = SubResource("Image_k4fhf")
...
shader_parameter/terrain_heightmap = SubResource("Image_k4fhf")

@akien-mga Can this be reopened please?

KoBeWi commented 2 years ago

@tinmanjuggernaut Does it happen in a new project too? Do you have some MRP? I'm using beta3 and the issue is completely gone for me.

KoBeWi commented 2 years ago

Nevermind I had this happen again. Not sure how to reproduce it this time, it was completely random. (although I had the project opened twice)

In my case the changed resources were materials.

TokisanGames commented 2 years ago

Note that the original report, which you fixed for default bus, was the uid for top level resources.

[gd_resource type="AudioBusLayout" load_steps=2 format=3 uid="uid://mebhjwywmmgu"]

My followup, and everyone else's issue was also for sub resources, which are still not fixed.

[sub_resource type="Image" id="Image_cbjwt"]

Make a theme. Godot changes it every time you save it. All of my scenes with sub_resources get changed nearly every time they are resaved and run.

TokisanGames commented 1 year ago

@Calinou This is incorrectly marked as "Done" on the roadmap. It's still a daily issue. Thanks.

Related https://github.com/godotengine/godot/issues/68672

Eoin-ONeill-Yokai commented 1 year ago

So I have a reproduction project that might be useful, with a few caveats.

The first is that the UID of a file can sometimes change if you play the game immediately after loading the project, though the occurrence of this is seemingly rare. My assumption would be that this happens because you play the game (and in essence, save the scene) before the cache is entirely built. This may vary based on your system configuration and speed of your drives too -- but it's much harder to achieve so far.

The second is easier. If you take light-plane.gdb and extract the mesh information to the root asset directory, you can save and quit and commit the git repository included in the zip. (The commit is only there to "track" when the change occurs) When you reopen the scene, and save, it will change the tscn file to match the .import that was made after reimporting the file. You can double check this by using git diff, you'll see that the "reassigned" uid is equal to the value of the .import file that exists, meaning that it must have changed at some point in that process.

So, if I were to take a guess, the issue here probably has to do with the reimporter changing the uid of a resource after extracting internal resource to external filesystem resources. Perhaps because the base resource is copied when extraction occurs in the reimporter in question?

Minimal Reproduction Project

bug62258_random_uid_change.zip

InnPatron commented 1 year ago

So, specifically for FontFile:

Backtrace (ignore the lines. I have some test code mixed in):

#0  Resource::Resource (this=this@entry=0x5555791fb3f0) at core/io/resource.cpp:463
#1  0x0000555559e11e09 in Image::Image (this=0x5555791fb3f0) at core/io/image.h:313
#2  Ref<Image>::instantiate (this=0x7fffffffc210) at ./core/object/ref_counted.h:227
#3  Image::create_from_data (p_width=256, p_height=256, p_use_mipmaps=p_use_mipmaps@entry=false, p_format=Image::FORMAT_LA8, p_data=...) at core/io/image.cpp:2112
#4  0x0000555556c516dc in TextServerAdvanced::_font_get_texture_image (this=0x55555d7503c0, p_font_rid=..., p_size=..., p_texture_index=0) at modules/text_server_adv/text_server_adv.cpp:2544
#5  0x0000555556d9ef94 in TextServerAdvanced::font_get_texture_image (this=<optimized out>, arg1=..., arg2=..., arg3=<optimized out>) at modules/text_server_adv/text_server_adv.h:775
#6  0x0000555558bc78ec in FontFile::get_texture_image (this=0x55556ca51b00, p_cache_index=0, p_size=..., p_texture_index=0) at scene/resources/font.cpp:2434
#7  0x0000555558be568b in FontFile::_get (this=0x55556ca51b00, p_name=..., r_ret=...) at scene/resources/font.cpp:1252
#8  0x000055555a224e54 in Object::get (this=this@entry=0x55556ca51b00, p_name=..., r_valid=r_valid@entry=0x0) at core/object/object.cpp:376
#9  0x0000555558d88bbf in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffffc930, p_variant=..., p_main=<optimized out>) at scene/resources/resource_format_text.cpp:1807
#10 0x0000555558d88954 in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffffc930, p_variant=..., p_main=<optimized out>) at scene/resources/resource_format_text.cpp:1836
#11 0x0000555558d88f1d in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffffc930, p_variant=..., p_main=<optimized out>) at scene/resources/resource_format_text.cpp:1820
#12 0x0000555558d89506 in ResourceFormatSaverTextInstance::save (this=0x7fffffffc930, p_path=..., p_resource=..., p_flags=<optimized out>) at scene/resources/resource_format_text.cpp:1893
#13 0x0000555558d8e833 in ResourceFormatSaverText::save (this=<optimized out>, p_resource=..., p_path=..., p_flags=96) at scene/resources/resource_format_text.cpp:2254
#14 0x0000555559eabbff in ResourceSaver::save (p_resource=..., p_path=..., p_flags=p_flags@entry=96) at core/io/resource_saver.cpp:121
#15 0x00005555571caede in EditorNode::_save_external_resources (this=<optimized out>) at editor/editor_node.cpp:1670
#16 0x00005555571e388a in EditorNode::_save_scene (this=0x555560f5c4e0, p_file=..., idx=-1) at editor/editor_node.cpp:1748

The addresses of the Images generated here corresponds with the address of the Image serialized as a sub_resource.

My guess: preview Images for Resources are not being cached properly.

I'm not sure how to fix this though if someone else wants to take a stab at this.

InnPatron commented 1 year ago

For FontFile, the offending code lies in modules/text_server_adv/text_server_adv.cpp:2534:

Ref<Image> TextServerAdvanced::_font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const {
    FontAdvanced *fd = font_owner.get_or_null(p_font_rid);
    ERR_FAIL_COND_V(!fd, Ref<Image>());

    MutexLock lock(fd->mutex);
    Vector2i size = _get_size_outline(fd, p_size);
    ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Ref<Image>());
    ERR_FAIL_INDEX_V(p_texture_index, fd->cache[size]->textures.size(), Ref<Image>());

    const ShelfPackTexture &tex = fd->cache[size]->textures[p_texture_index];
        // Always returns a new Image resource
    return Image::create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
}
InnPatron commented 1 year ago

Possible solutions:

InnPatron commented 1 year ago

TextServerAdvanced will cache the Image

Looks like it technically already caches it as an ImageTexture in ShelfPackTexture.

Replacing:

return Image::create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);

with

return tex.texture->get_image();

fails because it eventually reaches TextureStorage::texture_2d_get() (which allocates a new Image).

FontFile will no longer serialize Image as subresources (by not serializing the fallback property)

Breaks a bunch of stuff

I also tried omitting the images entirely from serialization which broke some more things in the editor.

akien-mga commented 1 year ago

CC @bruvzg

bruvzg commented 1 year ago

Images in the font are pre-rendered glyph, so if theme get it embedded as subresource it will include all glyphs that were used at this point and a copy of the font file, this is a pointless waste of space. If it's MSDF font, some pre-rendering is useful, but only if it's done at import. So FontFile should not be ever included as a subresorce at all. Themes should use it as an external resource only.

bruvzg commented 1 year ago

Font itself never need a persistent Image since it's modifying raw data and updating textures all the time, and externally modifying these Images are not supported either (unless you're also changing a lot of other font data).

So I guess it might be better to directly serialize tex.imgdata + tex.texture_w + tex.texture_h + tex.format (as is or encoded to PNG) as a PackedByteArray instead.

But something should be done with a Theme to prevent it from embedding fonts as well.

Rindbee commented 1 year ago

I found a situation that might be related to this. Related to #69794.

When moving or renaming a resource file A, another resource/scene file B that depends on this resource A will be modified. B's title tag will lose uid information. If B is opened and saved again, B will generate a new uid, and then update another resource/scene file C that depends on resource B. And so on, if the project has a long chain of dependencies on external resources. This can happen quite often.

https://github.com/godotengine/godot/blob/05097ded0a915cd6c083f15dab08da2bdc0770b8/scene/resources/resource_format_text.cpp#L928-L933

#69890 will copy title tag text as-is, which should help in this case.

TokisanGames commented 1 year ago

This is still not fixed and should probably be reopened again. See continuing discussion in https://github.com/godotengine/godot/issues/68661#issuecomment-1499139373

KoBeWi commented 1 year ago

It's fixed, the discussion you linked is about something different.

TokisanGames commented 1 year ago

The issue discussed in the other comment was brought up on this ticket in october.

https://github.com/godotengine/godot/issues/62258#issuecomment-1280937641 https://github.com/godotengine/godot/issues/62258#issuecomment-1285056930

Subresource references have still not been fixed.

Rindbee commented 1 year ago

@TokisanGames If dependent files are moved or renamed, it may be related to https://github.com/godotengine/godot/issues/69794#issuecomment-1499758039.

Vennnot commented 1 year ago

I agree with above, still not fixed. I have hundreds of resources in my project and I have lost weeks worth of progress chasing down this bug.

TokisanGames commented 1 year ago

@Vennnot I was able to resolve it on our project. But you need to change things in your files. The last issue for me was subresources. UIDs and subresource IDs are different things.

If new UIDs are showing up, on every save, then strip them out of all files and resave. Eventually they'll stop generating new UIDs when not necessary. https://github.com/godotengine/godot/issues/68661#issuecomment-1372115461 https://github.com/godotengine/godot/issues/68661#issuecomment-1465258995

However, my persistent issue was subresources, which are not UIDs. I resolved it by removing resources marked as "local_to_scene", and removing all images saved as text within scenes. Both regenerate new subresource IDs on every save. Including in the theme. If you have an original gd3 theme saved as tres, it's filled with images. Either drop them or save them as links to binary images. Read from here to the end. https://github.com/godotengine/godot/issues/68661#issuecomment-1499245624 Especially the conclusion https://github.com/godotengine/godot/issues/68661#issuecomment-1499786691

BrixsterPlanet commented 11 months ago

This issue still persists for me and my team. v4.2.dev4.mono.official [549fcce5f]

Can this be reopened?

image

AThousandShips commented 11 months ago

Please open a new issue after testing a current version (dev4 is over two months old)

We do not reopen issues that were once confirmed fixed, as the issue is different, same symptoms but different cause means different issue

joined72 commented 11 months ago

From the following post, the issue seems to be FULL presents on the 4.2b4 too :( https://discord.com/channels/212250894228652034/1171095147518365736/1171095147518365736

AThousandShips commented 11 months ago

Again, please open a new issue as this specific bug is resolved and any broken behaviour now is a separate bug

joined72 commented 11 months ago

What do you think to use as temporary workaround (until this bug isn't fixed) the following custom .gitignore file?

# Godot 4+ specific ignores
.godot/
# Does not ignore the Resources UID cache file
!.godot/uid_cache.bin

Edited after 4.2.1 release:

I don't know if this bug was really fixed in the latest 4.2.1 release, anyway this workaround works simply adding the ".godot/uid_cache.bin" Resources UID Cache File to the git repository, so to can restore it in case of Resources UID corruption, but this workaround works ONLY if you are a solo developer, otherwise can cause ".godot/uid_cache.bin" Resources UID Cache File conflicts for developers that are working on different resources at the same time. But if you are the unique developer that are working on your game, also working from different workstations, no problems.

I hope this can help. :)

Harox64 commented 10 months ago

@joined72 Hi, can you give some feedback on this workaround? I'm working on a new project in a team and I thought to do the same to prevent UIDs changing all the time. Files keep changing just because of those ID and since committing them can cause problem later, I prefer to correct this right now. But if it cause more problems I won't do it. Thank you.

joined72 commented 10 months ago

@joined72 Hi, can you give some feedback on this workaround? I'm working on a new project in a team and I thought to do the same to prevent UIDs changing all the time. Files keep changing just because of those ID and since committing them can cause problem later, I prefer to correct this right now. But if it cause more problems I won't do it. Thank you.

I don't know if this bug was really fixed in the latest 4.2.1 release, anyway this workaround works simply adding the ".godot/uid_cache.bin" Resources UID Cache File to the git repository, so to can restore it in case of Resources UID corruption, but this workaround works ONLY if you are a solo developer, otherwise can cause ".godot/uid_cache.bin" Resources UID Cache File conflicts for developers that are working on different resources at the same time. But if you are the unique developer that are working on your game, also working from different workstations, no problems.

I hope to have help you. :)

Harox64 commented 10 months ago

@joined72 It makes sense. With the team it won't be possible. Thank you for you time and the fast reply.

TimCoraxAudio commented 8 months ago

I'm still coming across this problem. Can this be re-opened please?

KoBeWi commented 8 months ago

Please attach a minimial reproduction project and/or some reproduction steps. With no information the issue is not actionable.

kawht commented 8 months ago

I am battling this severely. Godot's resource management seems to break so easily when files get moved, renamed, or just out of the blue. My projects that I have sunk many hours into, just come suddenly screeching to a halt when a main component of my game's .tscn file gets corrupted out of nowhere. I then have to spend hours tracking down what change I made.

TimCoraxAudio commented 8 months ago

Please attach a minimial reproduction project and/or some reproduction steps. With no information the issue is not actionable.

I have been struggling to accurately reproduce this issue over the last week. My best guess so far is that each computer is determining the UIDs in different ways even though they are running identical OSs and Godot versions. I'll keep trying to figure it out and get back to you

I am battling this severely. Godot's resource management seems to break so easily when files get moved, renamed, or just out of the blue. My projects that I have sunk many hours into, just come suddenly screeching to a halt when a main component of my game's .tscn file gets corrupted out of nowhere. I then have to spend hours tracking down what change I made.

I am so with you here. This is so insanely frustrating to deal with

KaletheQuick commented 8 months ago

I am also having this problem. I do not have a reproduction project, but I am wondering what other systems people are using? I'm On Linux mint on a Framework 13 12th gen Intel. I'm about to swap the motherboard to the AMD one, so I'll see if different hardware causes a change.

kawht commented 8 months ago

Glad I am not alone! I had an entire project get lost due to some sort of domino effect causing every .tscn to get corrupted a month ago. I hope we can figure this out.

I'm trying to get a project demo sorted, but it still appears so randomly it's hard to nail it down. For those who want some more info, I mostly have been using Godot 4.2.1-stable when the problems occur. I recently went to Godot 4.2.2-rc1 to see if maybe that helped, but it did not. I also get these problems most notably when I am trying to import a scene file from another project into a new one. Like a "player.tscn" or maybe a "explosion.tscn". Everything is corrupted on import, after clicking "Reload current project", restarting, re-importing, etc... If it somehow doesn't end up being corrupted, the dependency window pops up, and when I fix all the missing deps, it still remains un-openable!

My system specs: Windows 10.0.19045 Build 19045 12th Gen Intel(R) Core(TM) i9-12900K NVIDIA GeForce RTX 4070 Godot versions tested: 4.2.1-stable, 4.2.2-rc1

My recent list of errors: ERROR: Attempt to open script 'res://example/scenes/Airplane/visuals/Steering/Steering.gd' resulted in error 'File not found'. at: (modules/gdscript/gdscript.cpp:1025) ERROR: Failed loading resource: res://example/scenes/Airplane/visuals/Steering/Steering.gd. Make sure resources have been imported by opening the project in the editor at least once. at: (core/io/resource_loader.cpp:274) ERROR: res://visuals/Steering/Steering.tscn:16 - Parse Error: at: _parse_node_tag (scene/resources/resource_format_text.cpp:284) ERROR: Failed loading resource: res://visuals/Steering/Steering.tscn. Make sure resources have been imported by opening the project in the editor at least once. at: (core/io/resource_loader.cpp:274) ERROR: res://ui/3d_tracker_ui.tscn:10 - Parse Error: at: _parse_node_tag (scene/resources/resource_format_text.cpp:284) ERROR: Failed loading resource: res://ui/3d_tracker_ui.tscn. Make sure resources have been imported by opening the project in the editor at least once. at: (core/io/resource_loader.cpp:274) ERROR: res://planes/Drone.tscn:162 - Parse Error: at: _parse_node_tag (scene/resources/resource_format_text.cpp:284) ERROR: Failed loading resource: res://planes/Drone.tscn. Make sure resources have been imported by opening the project in the editor at least once. at: (core/io/resource_loader.cpp:274) ERROR: Failed to instantiate scene state of "res://planes/Drone.tscn", node count is 0. Make sure the PackedScene resource is valid. at: (scene/resources/packed_scene.cpp:141) ERROR: Failed to load scene dependency: "res://planes/Drone.tscn". Make sure the required scene is valid. at: (scene/resources/packed_scene.cpp:222) ERROR: Failed to load scene dependency: "res://planes/aircraft_spawn.tscn". Make sure the required scene is valid. at: (scene/resources/packed_scene.cpp:222) ERROR: Failed to load scene dependency: "res://planes/Airship.tscn". Make sure the required scene is valid. at: (scene/resources/packed_scene.cpp:222) ERROR: Index p_idx = 1 is out of bounds (edited_scene.size() = 1). at: remove_scene (editor/editor_data.cpp:626)

Some scenes are openable, some are not. The ones that aren't state that they are corrupted. The errors stating that the files don't exist is bs too. But even with all these errors.... My game still runs when I hit F5! What in the world is going on?

Here's the big whoop, even if I revert to an older version of the file (that is now "corrupted") using git, it still says it is corrupted. This leads me to beleiver the external resource UID system, is not updating properly with updated files. "Reload current project" doesn't help either, and sometimes can WIPE my .tscn file. The error happens a lot when you don't properly save certain files when you exit the Godot program, which then causes a bunch of "file corrupted" errors when you restart.

I want to help, if anyone needs more info, projects files, etc let me know.

TimCoraxAudio commented 8 months ago

Here's an interesting observation:

I reset my UIDs on my desktop using this command find . -name \*.tscn -exec perl -i -pe 's/ ?uid=\"uid:\/\/[a-zA-Z0-9]+?\"//g' {} \; as recommended from https://github.com/godotengine/godot/issues/68661#issuecomment-1372115461 and got Godot to save all scenes Scene -> Save All Scenes, then committed and pushed these UID changes to Git (which were all my png assets btw). I then pulled these changes on my laptop and got Godot to save all the scenes. Git showed that Godot had changed these png UIDs again. I reverted the changes, then deleted the .godot directory in the project and resaved the scenes. There were no UID updates after this.

This makes me wonder if the UID caches are getting out of sync because I don't have my .godot folder committed to Git

kawht commented 8 months ago

I agree, I never had my .godot file committed because it contained a bunch of fluff that would have to get committed over and over again. But that is where the cache is. I just don't think the current resource system is very stable still. In the past, I still had issues when I had the same cache.

betalars commented 6 months ago

@TimCoraxAudio

This makes me wonder if the UID caches are getting out of sync because I don't have my .godot folder committed to Git

Yes, but the .godot Folder is not intended to be committed to git. That is why it is being ignored by default.

You could make a somewhat usable workaround by syncing this folder until this issue is resolved, but that is also only feasible, when you do not have to deploy to somewhere from git.

FabriceCastel commented 5 months ago

Just wanted to note that in order for @joined72 suggested workaround, you should add the following .gitignore in your .godot directory:

/*
!/uid_cache.bin

and then remove the line containing .godot/ in the .gitignore in your root dir. If you don't break it out like that, the ignore rule that omits the .godot dir will take over and git won't track .godot/uid_cache.bin.

brevven commented 1 month ago

I have this same issue when working on a project with another developer (have had in both 4.2 and 4.3). It happens frequently, but is hard to reliably reproduce because it requires two different computers.

My question is, given that UIDs are not stable, is there any reason to commit them to VC at all?

I am considering setting up a .gitattributes filter to clean out all UIDs from version control. That way each local version of the project can have its own "local UIDs" and nobody else ever sees them.

KoBeWi commented 1 month ago

Unstable UIDs are a result of a bug. Sometimes they are caused by the user, e.g. when one person adds new texture, imports and commits it, but does not commit .import file, another person will import it again and reset UID.

UIDs make the project more resilient to breaking dependencies when files are moved. Not commiting them would make unique UIDs generated by every person that imports a file or opens a scene, which can break them.

brevven commented 1 month ago

Thanks for the reply. Incidentally, we always commit imports alongside assets. UIDs just sometimes are changed. It's a similar presentation to the initial issue you reported, but less reliably reproduced and seems to always occur due to differences between two different development environments.

Also, after reading your comment and looking more in depth, it seems my issue might be primarily impacting [ext_resource type="PackedScene" ...]. I couldn't find an instance of other resource types being impacted, but that doesn't mean they couldn't be 🤷 And unfortunately, I still can't re-create it reliably enough to file a useful new issue.

lucasrumney94 commented 4 weeks ago

sometimes my computer vs. my teams computer adds or removes UID in very noisy commit-back-and-forth changes that I either have to ignore every commit or deal with. Is there a way to pick a UID and then fix this problem? It seems to be happening to more and more scenes and assets over time making it impossible to commit changes easily.