-
-
Notifications
You must be signed in to change notification settings - Fork 21.9k
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
Crash with Godot 4 when setting value with "@tool" #61660
Comments
I didn't observe a crash in this particular case, but sometimes it crashes when saving scripts, indeed. |
2022-06-03.16-46-45_Trim.mp4instant crash when value is setted |
Yeah, there is a crash. I catch the following log with VisualStudio:
repeated a million times after
Seems like an infinite recursion with the following stack overflow. |
This is caused by a pretty significant change I just discovered in Godot 4 from Godot 3. In Godot 4, values cannot be set outside of the setter. In Godot 3, they could be set anywhere in the downstream setter callstack. The code posted would likely have worked in Godot 3. I don't know if the change is intentionally designed or if this is an unintented bug. If the former, it should be documented somewhere with clear examples. The original code recurses until the callstack fills up and the engine is killed:
One cannot fix it with either or both of these
You can do this:
However if you only want to update when the value has changed, GD3 was more supportive of that as you could change values anywhere in the setter callstack. Now you have to do something like this:
|
Here's another example where this new behavior may be a problem for a lot of projects: I'm calculating camera fov and focal_length. The values inversely correlate. Basically, both variables need to change simultaneously to be correct. In Godot 3 I could set fov and have it change focal_length, or vice versa. Perhaps there was just a recursion checker that broke out of crappy code and now that's gone, idk. However right now I need to do additional work to update both values w/o triggering infinite recursion. The simple code below should not crash the engine. It should just print an error and stop the script. This breaks the engine with infinite recursion when you change a value in the inspector (or upon scene load w/ nondefault values):
Meanwhile, in Godot 3, this works fine w/o infinite recursion:
This does work in GD4.
Then I have even another example where in a public function I set a variable, but the variable setter also calls this function. Since outside functions can't set variables w/ setters I'm still chewing on what sort of hackish solution will work around this. e.g. here's a simplified example
In Godot 3 I can either set the focus_point in the inspector or via script, or I can call the focus_at function to have it recalculate. In GD4, I'm looking at using a hacky sentinel public variable or timer to avoid redundant calls to focus_at(). So before I spend time refactoring all of my setters throughout my game, I'd really like to know if this new behavior is just a bug that will be reverted back to GD3 behavior, or is it a new design philosophy?
|
Hey @vnen, can you answer this question please? Thanks. |
I was facing the same problem until I discovered an alternative syntax for the set function in Godot 4 which behaves differently from the those shown above. Here is color modification example but redone with the alternative set syntax:
And here is the same color example but with each color variable setting each other:
I tested each of these on my end and it works fine with no crashes at all. So maybe the change in the set function was intentional after all? |
This was tested on the alpha 13 dev snapshot if that helps. |
@Kwu564 Thank you for this. Yes indeed, using the alternative format exhibits the Godot 3 behavior, allowing us to set variables in external setter functions, without any checks for recursion or special workarounds. I can confirm everything you wrote. The code that crashes the engine in my post above works as it did in GD3 if using your alternate format. It's good that we now have a way to use the familiar behavior. But now in the engine has a lurking, engine crashing bug. Use the wrong format and descend into infinite recursion until your call stack blows up. Yikes. And even if the crashing is fixed, it's not good that setters have two entirely different behaviors depending only on code formatting! I think a good solution would be to just remove the first format and behavior entirely. I don't like my setter function implementation in the middle of my variable declarations. And I certainly don't like the more strict behavior or the crashes. I've already been moving my code to the alt format to use the GD3 behavior. |
Everything is documented here: https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/gdscript_basics.html#properties This is a standard example of infinitely recursive function. You can achieve the same with func infinity():
infinity() There is no way to prevent such crashes other than limiting stack size (which I think no language does, given that stack overflow is a common error). The behavior of setters is not going to be changed. |
Godot version
Godot 4 alpha 9
System information
Windows 10
Issue description
Godot 4 editor crash when setting value with "@tool" and "set"
Steps to reproduce
Minimal reproduction project
CrashGodot4Setter.zip
The text was updated successfully, but these errors were encountered: