Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Class names stop working after a while #76380

Closed
blackears opened this issue Apr 23, 2023 · 38 comments · Fixed by #92303
Closed

Class names stop working after a while #76380

blackears opened this issue Apr 23, 2023 · 38 comments · Fixed by #92303

Comments

@blackears
Copy link

blackears commented Apr 23, 2023

Godot version

v4.0.2.stable.official [7a0977c]

System information

Windows 10, Compatability

Issue description

I'm getting a problem where class names that I define in GDScript just stop working after a while. I'm not sure what is causing this. I am just noticing that when I'm working on a project where I've defined a lot of classes using class_name MyClassName the name will just stop being recognized after a while. Sometimes if I restart the editor two times it will become available again.

Sometimes a class name that I had been using for a long time just stops working and I have to append a '2' to the class name to be able to use the class again. This is not due to name collisions - these are the only classes in my project with this name and they're complicated enough that I doubt they are part of the core GDScript api.

I suspect the Godot editor is caching something that is persisting between sessions, and whatever that is is interfering with the ability of the script to compile

Steps to reproduce

I'm not sure what causes this. It might be related to duplicating a .gd resource and then editing it, but not always. I'm just noticing that after working on a project for a while, some class names just stop being recognized.

Minimal reproduction project

N/A

@blackears blackears changed the title Class names stop working after Class names stop working after a while Apr 23, 2023
@trollusk
Copy link

I've had this problem as well. Sometimes class_name just doesn't work (and the name stays grey), especially if you change the class name in an existing script. Repeatedly editing and saving seems to eventually wake Godot up and get it to register the class.

@vfig
Copy link

vfig commented Jun 2, 2023

one specific set of steps (likely not the only one) that is capable of triggering this problem:

  1. make a script Foo.gd with class_name Foo
  2. in the file system panel, duplicate Foo.gd, call it Bar.gd
  3. change the line in Bar.gd to be class_name Bar.

at this point one would expect both class names to be working. but the Foo class name will not be recognised properly. this can break previously working scenes; for example, a script that does find_children("","Foo") in a scene with objects with Foo.gd attached will return an empty array while this class name is 'broken'.

opening Foo.gd, editing its class_name declaration, saving, then editing it back and saving again will get it working again.

@AThousandShips
Copy link
Member

AThousandShips commented Jun 2, 2023

@vfig This is caused by the fact that you overwrite the class, it'd be hard to detect this change as you would have to go through evert script to find the one that was overwritten

@vfig
Copy link

vfig commented Jun 2, 2023

@AThousandShips no, i did not overwrite the class. ItemGem.gd was intact and unchanged.

in fact, if (before i edited ItemGem.gd to force a fix) i had deleted the new script, i would have had a completely unchanged working copy (as reported by git status) that no longer worked correctly: an extremely unhappy situation.

@AThousandShips
Copy link
Member

AThousandShips commented Jun 2, 2023

You did, you added a new class with the same class_name, this sets the script associated with that name to the new script, as I explained above, the problem is:

  1. Script A declares a class named "X", "X" now points to A
  2. Script B declares a class named "X", "X" now points to B
  3. Script B declares a class named "Y" instead, "Y" points to B, "X" becomes unknown, as no tracking of previous file is done

@vfig
Copy link

vfig commented Jun 2, 2023

…while the script that had previously been associated with that class name was still there, unchanged, with its class_name declaration intact.

it would be reasonable in this situation for godot to show an error that there is a duplicate class name; and then when i have edited one file or the other to resolve that, for it to update its cache so that both (now different) class names are associated with their respective scripts.

it is not reasonable for it to lose track of the association. it is not reasonable if one copy of the project fails to work while a completely clean checkout of the project in a new folder, with identical code and resource files, would work.

(and it is not particularly reasonable to reply to a bug report with “fixing this would be hard” and “you’re holding it wrong”.)

@AThousandShips
Copy link
Member

AThousandShips commented Jun 2, 2023

it would be reasonable in this situation for godot to show an error that there is a duplicate class name

Yes, that is a good suggestion, but tracking this isn't simple

and it is not particularly reasonable to reply to a bug report with “fixing this would be hard” and “you’re holding it wrong”.

Just stop here, I never said any of those things or anything like it, be professional and reasonable please

I am simply explaining what's going on here, not accusing, or saying "we won't fix this", I am saying it's a complicated thing, please be respectful, professional, and refrain from being so combative, please see the code of conduct

@blackears
Copy link
Author

I've run into a similar situation to the one @vfig is describing. I don't know how Godot handles the tracking, but a minimal solution could be to add a button that just has the editor discard everything and rebuild the tracking from scratch - akin to what a 'build clean' would do in a C++ environment.

@AThousandShips
Copy link
Member

That's a really good idea actually, for many reasons

@vfig
Copy link

vfig commented Jun 2, 2023

no, that is a terrible idea. if godot’s cache cannot handle a temporary class name conflict without breaking the project, pushing that problem back onto the user with a “clean build” button or similar is wrong.

a godot user should fully expect that the scripts they write work as written, and not have to guess if a cache they dont know about needs to be wiped for their project to work correctly.

@AThousandShips
Copy link
Member

AThousandShips commented Jun 2, 2023

How do you suggest to solve it? How do you track replaced class names? Can you point to the changes in the code to make to fix this?

Do we reload every single script each time one changes? Keep a long list of old scripts? All I'm saying is that your approach to this isn't helpful, I've said how this occurs, I've never said this was expected or like it should be, nor that this can't or won't be fixed, simply that it's a complicated thing, and just saying "fix it" isn't helping

As I said a warning on collisions is a good idea

@vfig
Copy link

vfig commented Jun 2, 2023

i do not know the code that handles this, so i cant point you to specific lines or anything. i can suggest an approach that would resolve the issue with the replication steps that i encountered (though of course the OP report might be a different caching bug that would not be resolved by it):

i am assuming that the cache is roughly a dictionary mapping class names to one script file.

when a new class_name declaration is processed, check the previous file associated with it in the cache. if the previous file does not exist, or is the same as the file currently being processed, replace the cache entry.

if the previous file exists and is not the same as the one being processed, that is a conflict. update the cache entry with a flag to indicate that it is in conflict, and a list of the files involved in the conflict (not a “long list”, it would be rare to have more than two). push an error to alert the user to the problem. (possibly this should be a compile error entirely preventing these scripts from running, but i dont know enough about the system to say).

when a script involved in a conflict is edited or deleted, check all the scripts in the list to see if the conflict is now resolved. if it is, remove the flag and the list of conflicts, and update the cache entry to be associated with the appropriate script.

@blackears
Copy link
Author

I would be in favor of some sort of 'scrap the whole thing and start from scratch' emergency option. Godot is operating in a complex environment and does not have complete control of the source. Eg, switching between branches with version control could completely alter what the project even contains. Addons can also have side effects on what the IDE is doing.

Cleaning the build is essential in a C++ environment simply because there are so many weird things that can get your project out of sync with what a fresh build would produce.

@trollusk
Copy link

trollusk commented Jun 2, 2023

@AThousandShips Now you are being combative. Who has said "fix it"? The users in this thread are reporting a serious bug. It is not reasonable for you to demand that bug reporters specify how to fix the bug.

@AThousandShips
Copy link
Member

AThousandShips commented Jun 2, 2023

I am sorry, I was responding to what to me felt like a combative attitude declaring that it's unhelpful to explain that it's hard, and what felt like a dismissive attitude of "just fix it" or "it's unreasonable that it works like this", that's why I responded in an unreasonable way, I felt the attitude dismissed the actual work involved in fixing this, following the putting of words in my mouth above, and that was unfair of me

@vfig
Copy link

vfig commented Jun 2, 2023

@blackears the c++ situation is not exactly a model to be imitated! however in this instance the bug is happening entirely within godot’s purview, editing files only within its own editor.

@blackears
Copy link
Author

@vfig not is you're using source control. Files can be changed outside of the editor.

@vfig
Copy link

vfig commented Jun 2, 2023

@blackears no files are changed outside the godot editor in the reproduction steps i described.

@FeralBytes
Copy link
Contributor

FeralBytes commented Jun 29, 2023

@blackears I can confirm this experience (@vfig 's experience that is) and I am using git, but I have not changed the current tree at all. I have only used git to snapshot the project, yet Godot is forgetting the class_name.

@donn-xx
Copy link

donn-xx commented Aug 17, 2023

Godot 4.1.1 seems to still have class_name issues. I posted on a similar thread: #30048 (comment)

Not sure which issue number is the right one to join.

@daenvil
Copy link

daenvil commented Oct 11, 2023

I have been using 4.1 for some months and I can confirm that I encountered this issue multiple times, mostly when moving or duplicating files (all within the editor). I circumvented it by renaming classes whenever the error happened. The worse case was recently when I moved my project to a new location and every class name broke.

I think this might be related to #78642 , where a "update cache" button is also suggested as a solution.

@Wad67
Copy link

Wad67 commented Oct 12, 2023

I have also encountered this issue just now, I recently cloned my game repo on new hardware, imported it and godot began complaining about not finding class_name definitions.

'Solved' by right clicking the offending files, and moving them to the project root directory.

@lpares12
Copy link
Contributor

lpares12 commented Jan 6, 2024

Hitting this issue just now. Suddenly all the classes can't be found in any of the scripts. Had found it before and I could just restart Godot, or remove a class_name and add it again. But this time it does not work.

@donn-xx
Copy link

donn-xx commented Jan 6, 2024

Hitting this issue just now. Suddenly all the classes can't be found in any of the scripts. Had found it before and I could just restart Godot, or remove a class_name and add it again. But this time it does not work.

I have found 3 "fixes".

  1. Glacial: Open each script. Change class_name by one character. Save. Undo. Save again.
  2. Gradual: Delete .godot/global_script_class_cache.cfg
  3. Nuclear: Delete .godot/ entirely

@anvilfolk
Copy link
Contributor

Hitting this issue just now. Suddenly all the classes can't be found in any of the scripts. Had found it before and I could just restart Godot, or remove a class_name and add it again. But this time it does not work.

@lpares12 one day I hope to have time to look into this a bit more in-depth! Do you happen to remember renaming or duplicating a .gd file? That seems to be at the source of at least a few of these issues!

@donn-xx
Copy link

donn-xx commented Jan 6, 2024

@lpares12 one day I hope to have time to look into this a bit more in-depth! Do you happen to remember renaming or duplicating a .gd file? That seems to be at the source of at least a few of these issues!

I would say the glitch does happen when there is a lot of .gd file churn. I would say that duplicating another .gd file (that has a class_name) and then editing it (before you can change the class_name to something else) seems a good way to trigger this. Will have to try isolate it.

@lpares12
Copy link
Contributor

lpares12 commented Jan 8, 2024

@anvilfolk I didn't rename or duplicate anything that time. I was just playing around with an AnimationPlayer and some inherited scenes. Then I realized everything started crashing.

After a few more restarts and changing class_names, it started working again.

I think it might be related to a recursion problem. The file in question was defining class_name A and it had some references to class_name B. On b.gd (where I define class_name B), there are some references to class_name A. So I wonder if it has something to do with this? That doesn't explain why it happens not so often though.

@MayaKerr
Copy link

Has this been fixed or a reset cache button been added anywhere/ any plugin?

I accidentally committed to my repo with Godot open and it duplicate ALL of my files in my project. I went through and deleted the duplicates, but now none of my classes are working and I cannot get this fixed with restarts or renaming classes.

Since this issue was opened in 2023, now asking in 2024, has a fix been found or created?

@donn-xx
Copy link

donn-xx commented Feb 18, 2024

Has this been fixed or a reset cache button been added anywhere/ any plugin?

I accidentally committed to my repo with Godot open and it duplicate ALL of my files in my project. I went through and deleted the duplicates, but now none of my classes are working and I cannot get this fixed with restarts or renaming classes.

Since this issue was opened in 2023, now asking in 2024, has a fix been found or created?

No fix yet, afaik.

Go into .godot/ and open global_script_class_cache.cfg

Dig around in there and alter any weird looking stuff. Also try restarting your project multiple times. It tends to flush-out as you fix error messages.

Another trick I have used is to open the scripts and go to the class_name FOO and hold Ctrl while you hover over FOO. Sometimes this forces Godot to recognize FOO as a class. I also retype FOO and Ctrl+S : all this is kind of like editing the config file I mentioned above.

Good luck. Take it one class at a time with restarts in between.

@MayaKerr
Copy link

MayaKerr commented Feb 18, 2024 via email

@Roboticy3
Copy link

I've been working on a rather large project for a long time now, and this always comes up when trying to send the data to other devices over github! .godot is automatically added to the .gitignore in projects created with git version control. It seems like removing the class cache from the gitignore would solve this device issue from looking at the thread. Is there a reason it's added to the gitignore by default?

I for one have two devices I use to work on the game. One of them has a corrupted class cache and the other doesn't. After trying to remove the class cache from the gitignore and creating a test branch where the class cache is in the repository from the device with the "clean" cache, it looks like it works!

Since rebuilding the class cache from scratch is finicky, is there any reason the class cache needs to be automatically added to the gitignore?

@donn-xx
Copy link

donn-xx commented Apr 2, 2024

Without global_script_class_cache.cfg (as @Roboticy3 points out) Godot breaks. This is still the case on the latest main (compiled today).

If that file is missing, one gets compile errors on every mention of a class_name like classFoo.do_something()

Could Godot not somehow pre-process gdscript files to re-build that cache file before starting their execution?

At the moment I am having to do this weird thing with const and preload to superimpose a name onto each class so that it works:

Here, classfoo.gd is already using its own class_name:

class_name classFoo # <-- this one
extends Resource
etc.

But I have to alias it so:

const FakeClassFoo := preload("classfoo.gd") # The const name is the aliased class_name
..
var foo := FakeClassFoo.new() # which is weird
etc.

I have to do this so that, as that cache file comes and goes, the code does not break.

@donn-xx
Copy link

donn-xx commented Apr 3, 2024

Another issue is Plugin dev.

My gdscript relies on class_names in all sorts of ways. When I distribute the plugin, that global cache file does not go along with it, therefore there will likely be all kinds of broken behaviour for the end-user as names fail to resolve etc.

@Roboticy3
Copy link

That would explain why the plug-ins in my project often use the preloading method given by @donn-xx. If class cache is more trouble than it's worth to fix, maybe just updating the docs to suggest this style of importing would be a good idea.

@romgerman
Copy link

Just now we encountered this. After importing a project from git Godot cannot find any classes defined with class_name. But if you open your custom classes in the script editor (or vscode) then godot recognizes them. Also some addons (like DialogueManager) stops working after importing the project.

@donn-xx
Copy link

donn-xx commented May 22, 2024

I have written two plugins (gdscript) that rely on class_name. Despite the const trick above, there are cases where the class_name is important and when the plugins are installed, one gets the dreaded, "SCRIPT ERROR" with complaints about not knowing class names.

If the global_script_class_cache.cfg file of the plugin could somehow be merged with the one in the project its being installed into, that might be a hacky fix for now.

@donn-xx
Copy link

donn-xx commented May 22, 2024

I just cloned a Godot Project* and tried to run it. This is what you get. I have closed and opened and closed and opened, but it refuses to just parse the class names!

*(https://github.com/YuriSizov/boscaceoil-blue/)

SCRIPT ERROR: Parse Error: Could not find type "SettingsManager" in the current scope.
          at: GDScript::reload (res://globals/Controller.gd:34)
SCRIPT ERROR: Parse Error: Could not find type "VoiceManager" in the current scope.
          at: GDScript::reload (res://globals/Controller.gd:35)
SCRIPT ERROR: Parse Error: Could not find type "MusicPlayer" in the current scope.
          at: GDScript::reload (res://globals/Controller.gd:36)
SCRIPT ERROR: Parse Error: Could not find type "IOManager" in the current scope.
          at: GDScript::reload (res://globals/Controller.gd:37)
SCRIPT ERROR: Parse Error: Could not find type "Song" in the current scope.
          at: GDScript::reload (res://globals/Controller.gd:40)
SCRIPT ERROR: Parse Error: Identifier "ColorPalette" not declared in the current scope.
          at: GDScript::reload (res://globals/Controller.gd:47)
SCRIPT ERROR: Parse Error: Identifier "ColorPalette" not declared in the current scope.
          at: GDScript::reload (res://globals/Controller.gd:48)
SCRIPT ERROR: Parse Error: Identifier "ColorPalette" not declared in the current scope.
          at: GDScript::reload (res://globals/Controller.gd:49)
SCRIPT ERROR: Parse Error: Identifier "ColorPalette" not declared in the current scope.
          at: GDScript::reload (res://globals/Controller.gd:50)
SCRIPT ERROR: Parse Error: Identifier "ColorPalette" not declared in the current scope.
          at: GDScript::reload (res://globals/Controller.gd:51)
SCRIPT ERROR: Parse Error: Identifier "ColorPalette" not declared in the current scope.
          at: GDScript::reload (res://globals/Controller.gd:52)
SCRIPT ERROR: Parse Error: Identifier "ColorPalette" not declared in the current scope.
          at: GDScript::reload (res://globals/Controller.gd:53)
..
...
It goes on and on

How is this a thing?

@romgerman
Copy link

Turns out if you commit global_script_class_cache.cfg (I'm using git) then the project will not have any class_name errors after cloning (It was the problem for me because my gamedev partner couldn't run the game after getting sources).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.