godot: Some usages of `class_name` can produce cyclic errors unexpectedly
Bugsquad edit: This issue has been confirmed several times already. No need to confirm it further.
Windows 10 64-bit - Godot 3.1 alpha
Edit - Refined issue to focus on cyclic errors.
Certain uses of class_name
can produce cyclic errors in situations where there are no cyclic references, and in fact sometimes no other references outside of the single one given.
I’ve noticed this most frequently in tool script when using is
to make a class comparison, but it seems to happen at times in normal script situations.
Recreating it in a sample project has eluded me.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 110
- Comments: 81 (37 by maintainers)
Commits related to this issue
- Workaround for GDScript issue https://github.com/godotengine/godot/issues/21461. — committed to dkollmann/easycpp by dkollmann 3 years ago
The fix I was working on is still WIP and causing crashes. I’m not confident to merge such a big change it in beta stage, so it’ll likely be done in a 3.2.x release later.
I ask to please not bump issues without new information. We all know this happens, have already plenty of examples, won’t magically go away with more comments.
I’m currently trying to fix this at @JavaryGames, the solution is already underway. Not sure if it’ll make into 3.2 since it’s a big change (had to rewire somewhat how GDScript works internally) and we’re close to release, but maybe we can integrate in 3.2.1 or something. Will definitely be fixed in 4.0.
It will be resolved in 4.0 as part of the GDScript rewrite.
Not only this^^ but sometimes restarting Godot doesn’t work if you’ve gone in deeper than a couple files. And, occasionally, a restart is not needed if I do dummy edits on the files in cyclic lock, in just the right order. What I am currently having to do while refactoring and breaking several files at once is temporarily downgrade the var and parameter typing to just
Object
until everything is working again. And, then, put the correct typing back in, and then restart Godot. Working like this is brutal and I have a hard time recommending Godot until it is fixed. Okay, if you don’t need to code much, Godot is great. But, once you start classing stuff and renaming classes, forget about it. Classes don’t “just work” in Godot. They are a constant fight.So, regardless of whatever parts of this are being fixed in 4.0, it would be nice to at least be able to force a re-analysis of all dependencies in 3.x (or do it more often behind the scenes) so that we don’t have to restart or resort to other trickery all the time just to get the parts that do work… working again.
Sorry I’m not more useful, I don’t have access to Godot right now. But on 3.2.3 I often still get this problem whenever:
@harraps that will be done (as I said a few times in the thread), but it requires some fundamental changes in how GDScript is wired. I won’t touch this now since we’re close to release and this change will likely break compatibility.
I’m also getting the error shown in the original post (Windows x64 Godot 3.1 alpha):
However, it happens in a different context. I have 3 scripts which each have a different
class_name
, and each of them extend Node2D. The error does not occur unless one of the scripts references it with theis
operator. For exampleif some_var is Incomer
. The weird thing though is that if the same script references the other class_name, there’s no problem. And if the other script references the class_name in question, no problem either.So there’s a ClassA, ClassB, ClassC. If ClassC references ClassA with the
is
operator, then error at load time. If ClassC references ClassB, no error. If ClassB references ClassA, no error.None of the scripts are in the same scene, and all of the nodes are siblings (no ancestor relationship).
I’m not sure why it’s giving this error, I’ll have to investigate.
As has been mentioned a few times, this will be solved in 4.0 and no sooner. Not sure when other 4.0 features are marked done…
Yes, I have it in my public fork: https://github.com/vnen/godot/commits/gdscript-no-cycles
You might get some caching artifacts in the editor since everything is being reloaded all the time as you’re editing. But if you reach this problem it most likely won’t work when running even if you manage to get it error-free in the editor.
I’ve been hitting this one often in 3.1.1, and jumping through hoops to avoid it. Hoping it will be fixed in 3.2!
Just wanted to make a note that I hit the “is” class_name bug today as well.
I have reverted to using object.has_method(“name”) rather than testing if object is className
@Angular-Angel I’ve noticed that restarting Godot resolves the errors. It’s disappointing that I can’t use static typing in Godot with custom classes/types yet without bizarre errors popping up.
Well this should not be closed, no, the sheer amount of duplicate reports definitely show that there is something to fix 😃
I had a similar dependency issue when that prevented me to implement a Builder pattern using a static method:
Workaround described here to load class from source file path is nice but require to not change file tree without changing source code.
I use this trick to have current source file path even in static method (in which get_script() is not available):
with
This trick to get current class seems to work from anywhere. It is raw and can be used to avoid similar cyclic dependency issue waiting the global dependency fixing.
@Ploppy3 These fixes are due to massive changes that come with the GDScript rewrite and it’s likely not possible to cherry-pick them. You will have to upgrade to 4.0 if you want to have these fixes.
Not sure if more information at this point helps, but a workaround (that worked for me) is to change the
class_name
of the problematic class and then change it back. Which makes it seem to be cache-related.It happened to me at a line where I was casting a class member using
as
right after changing the signature of a method of the class to which the variable was cast to, but before I could fix the actual method. Then after fixing the method, the line kept giving this error, and it only stopped when I finally changed the cast class’ name to something else, and then changed it back.Hmm. The errors seem to have to do with the order that things are loaded in the editor window? I can get them to go away by closing and reopening files in the order in which they inherit. So, probably some kind of trouble around it not declaring things in some files. 😕
Edit: Actually no, it doesn’t matter what order I open files, or even if I have other files open at all. When I first load one of these files, they don;t show any errors, and won’t until I change them, and then all the errors show up. 😕
@bfishman script classes are not a feature in 3.0.x. That is why it is not working.
In 3.5.1, it seems sometimes
is
will cause a cycle whenas
will not:That seems like a bug, but also a potential workaround (for some use cases) until 4.0? This doesn’t seem to be one of the cases that goes away after a reload.
@MikeSchulze In this case, I feel like it’s partly a design issue:
WfcSlot
should probably not know aboutWfcSlotHistory
. Thesave
action should probably be on the latter.(This behavior/bug is annoying, though, don’t get me wrong.)
As I said before, it’s very easy to create cycles with
class_name
, especially when usingis
andas
. It’s less easy with paths, but you might bump into similar problems too. The problem is GDScript was never wired to work like that, so it depends too much on resource loading. I have some ideas to fix this (in particular just ignoring resource loading and doing shallow parse of dependencies directly), but this requires a structural change of the parser.Probably it will properly solved in next versions, since it’s not a good time to mess with this.
class_name
will be a “lesser feature” for now. You can still use it in some cases, but not as extensively as you expect.@avencherus the “class names” of script classes are global variables that reference the script. So…
👍
@HorseLuvver that is called an abstract class/interface, and it should work with autocomplete if you create dummy (virtual) empty methods just to declare its fields. These are basic concepts of Object Oriented Programming and are a feature of classes in general programming.
However, this does not cover all cases of circular reference. It does help to some extent and I have been doing so for some time now. It is good, albeit tedius, practice.
From the lead maintainers, unlikely to be backported to 3.x, since resources are allocated to 4.0. Anyone is free to open a pull request though.
hi @AliBouarab nice trick but this is only working on debug mode
I have this issue as well here are my two scripts.
When this fix will be come in the main line? It is super annoying because i use type save scripts and run very often into this problem. Today i run into not solfable situation.
Sorry, but I am a bit frustrated too, and I didn’t know about that workaround since you guys commented, I stopped typing my code a while a go, but I still miss it A LOT.
This might be a naive question but shouldn’t we get rid of this non-cyclic restriction. I mean other languages like Java, C#, C++, etc… can deal with types without issues…
I will periodically keep making an effort to tease it out. Wish I could be more help, but I’m imagining these will have to wait until those with deep knowledge of their implementation are working on their own projects and run head first into these problems. I would wager they’d know where to set their sights in that situation.
A quick summary of some of the issues (I’ll get these posted sometime in the coming weeks):
obj is MyClass
and there was no other connection or reference between the two. Though I don’t know if it is scanning the scene tree and counting its children as cyclic references.Just overall my experiences with
class_name
has been a nearly daily encounter with a lot of unpredictable, difficult to explain, and hard to reproduce errors. A lot of time is wasted dancing around it and trying to resolve them.I was really looking forward to them, and they absolutely would make coding certain things a whole lot more compact and readable. For practical time reasons I have to set them aside and opt out of using them in my current project.
Maybe in 4.0. X)
I’m going to revert to the old method of script paths. In doing so it would just be my own preference to use them all the way through to avoid any random
class_name
surprises, and to keep the code more consistent.This has nothing to do with the nodes in the scene. Cycles happens in the script themselves.
For now it’s quite easy to get cycles when using
is
andas
and if it happens it’s not really a bug, it’s the way it is. I’ll try to improve this but not for 3.1. The original report is a bug because there are no actual cycles in the code.@willnationsdev Oh neat, I see now. I wasn’t expecting class_name to work like that, or the custom type to be available to the match pattern . Thanks for sharing this tip Will.