-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Errors when changing scene using change_scene_to_file() #85852
Comments
I think if they are not affecting the game when run and not crashing it, I think it is just a Godot bug, it can happen, but if it is affecting the game, I think there is a thing. |
Both situations are caused by the change in 4.2 that makes In this case you'd need to defer both calls to |
I assume there are good reasons for this, but from a user perspective, it seems like more logical, user friendly and intuitive would be to deferred it internally as it was in earlier versions of Godot. Where can I read up on the reasoning for this change? Either way, these errors do not help much to find the cause or the fix for this issue. It's also not documented in the methods description:
|
It's discussed in https://godotengine.org/article/godot-4-2-arrives-in-style/#critical-and-breaking-changes with a link to the PR that changed it. There wasn't much discussion there at the time, as it was an attempt at fixing critical issues and we hadn't considered all implications. This was further discussed in #85251.
See the note you quoted :)
|
@akien-mga
This does not help. If the user is expected to only call this method deferred, it should say so in the method description. Moreover having to
|
It's not intended to only be called deferred. In most situations you can call it as is and have the scene change done right away. The errors you get come from doing tree manipulation during a physics callback, as they mention. You would have the same issue trying to remove a physics node in |
Except for UI, I have a hard time to imagine what kind of situations these might be. Most scene changing situations in my games and most games I see made by others are triggered by a physics body entering an Area or interacting with an Area, triggering a custom signal. Such as I tried to model here in the MRP.
I just tested this in Scene A of the MRP and I'm not sure what you mean. Both |
You're not just removing that collision object when changing scenes though, so it's probably triggered by some of the other bodies, otherwise why would that warning be triggered? |
The physics callback comes from area, not body. If you do |
Thanks to everyone who commented and tries to shine a light on these errors! I don't think the method names makes it clear on how to use them, neither does the description, and even after you all explaining, I still don't have a firm grasp on what is going on, why it is necessary we now have changing scenes be much more complicated, and confusing when it worked fine before (at least in my usage). That's from someone with more than 5 years of Godot experience. I can only imagine stuff like this would be a lot more confusing for someone starting out. Please keep in mind how most of you are daily work with the Godot source, that's not the experience or background knowledge of most Godot users. I'm not sure what is the solution here, if it is just better documentation or something else, but I feel like something needs to be done to make something as central to using Godot as changing scenes a lot smoother and less error prone. |
The change was made with the goal of making scene transitions safer and smoother And adding a specific error if changing the scene when in this state is being investigated, but the method name doesn't give any indication either way to the behavior, it's not named But I don't see how it's not transparent? It is documented and in the release post. This change was done early in the 4.2 release cycle and has been tested extensively and been there for testing by people using this behavior 🙂 |
Maybe this means As a new user, I learned very early on to use
I very much disagree.
I'm telling you as a long time user: It's not. For you, for akien or other contributors and C++ magicians, what is written in the release nodes and API description might sound totally obvious and self-explanatory. I have read both the documentation and the release post many times before creating this issue. To me, a non C++ user who does not work with the Godot source every day: Why we are getting these errors now, when used as explained in the OP and MRP, is totally opaque, non transparent. Please accept this point of view. |
Then how would it be transparent? How would it be more transparent than writing exactly how it changed? Please explain how you'd like it to be explained to be cleared than that 🙂 We can't really explain every are it affects, that's something that has to be worked out based on how you use it, because we can't anticipate every possible use case, unless people express or use them |
I don't understand what the problem was with I thought I knew what's going on, but I'm obviously wrong. Which is why I opened this issue.
Changing the scene when a character or other physics body enters an area or interacts with one is not a rare obscure usecase. It's THE most usecase for this method in any game. |
I'm not sure why this wasn't noticed, perhaps people were being safe and calling this method deferred to not do scene tree changes during physics callbacks But as I said, we're looking into adding specific clear errors, and the change was done with the goal to fix a number of bugs in the scene change sequence |
The main relevant changes were done in #78988 and #85184, perhaps this will give you more context on the why.
This was explained here #85852 (comment) - specifically 'manipulation during a physics callback'. Personally, I've always called this method deferred to avoid any potential problems. Usually games also have animations, and loading, instead of an immediate transition. |
I too used to use deferred to load my scenes, but somehow the latest engine changes broke it. get_tree().change_scene_to_file.bind("res://some_scene.tscn").call_deferred() Did not work for me, somehow it returned null, but what was null was the current scene? Or something like that, I forgot, but it looked like it was freeing before it was supposed to, and not having anything on tree to change to, error happened. Apparently this is the new expected behavior, or so that's what I understood from all of it, sometimes I find confusing in my mind trying to translate English in my head. Anyways, instead I used @Lippanon 's link, and that seems to be working here, with a little change on freeing the current scene:
And while the docs tell you what is going on, the how to do it is a bit vague with lots of options to go to, but few examples. Strangely tough, in the docs it tells you to free() instead of queue_free(), which not only results in error by attempting to free a locked object (Not calling it deferred), but also seems unsafe. |
I tried this in the MRP and it works with no errors, using v4.3.dev.custom_build [84692c6]. Notice that, in the demo above, the function that calls As for the docs you mention, they probably should mention 'deferred' somewhere, I agree. |
What would be the code to utilize this new behavior correctly? This print statement in this block returns null:
|
I am a new user who is accustomed to using C #, so the correct code for this issue is: This is a bit against habit |
The workaround works properly, but how do you get the result from the |
@freshlybakedhot your snippet no longer works in 4.2.1. |
It feels like change_scene_to_x functions are broken in 4.2 and @Lippanon's workaround is the way to go for now. I haven't encountered any issues with it so far and there doesn't seem to be any other stable solution. In my case, I noticed that on 4.2.1, using change_scene_to_file does not delete the previous scene. It's still available but orphaned and signal handlers are still called. The docs say the scene is deleted "immediately" but that isn't happening and it's impossible from a user perspective to know why it isn't happening. I'd have to dig into engine code. I tried to queue_free the orphaned scene/node after the call_deferred but it closes the game without errors. |
I feel like these methods ( If someone wants to change scene immediately (which is unsafe because it will give errors if invoked during physics callbacks, which again is really common), separate functions should be provided (such as My Elaboration: Now if someone wants to change the scene immediately instead of Godot doing it smoothly over time (to avoid errors) for him, he can invoke these methods appended with You can argue against this all you want, I can't change your anyone's mind, but the fact stands that the user now has to type more and think more about his physics objects possibly getting offed while in motion resulting in errors, which is overall a less streamlined experience than before where the method took care of it. |
These are some of the most common methods in Godot that almost every game would use. I don't think we should make the main way of using them feel like a workaround, especially since it worked fine for the most part beforehand. There's also the case where you want to do access something in the scene afterwards right after you switch to it, you would have to defer everything as well, forcing you to either call every line with defer(which is very inconvenient) or make a separate function/lambda for everything you want to do and defer that. The workflow is very iffy. |
- Add Script for changing level - Fix : Errors when changing scene using change_scene_to_file godotengine/godot#85852
Hey, +1 on this, and here is some input from a several-days-into-Godot noob. This is at 4.2.2-stable on Linux. at physics process when I do
It works, but once I let myself await:
Then scene changing line breaks and I have to rewrite as per recommended here:
Which then works. From very outside it occurs to me that upon using UPD. Of course, as per docs, first Anyways, from this useful conversation I take away a habit to change scenes asyncronously no matter what, thanks for that! Hope this helps, thanks! P.S. I think also it might be a good feature for editor to highlight such cases (if detectable statically) and suggest a correction (like «this future is never awaited» in PyCharm). |
Theoretically this is triggered by physics process incompatibility, but I'm hitting it directly from button presses: public override void _Ready()
{
base._Ready();
GetNode<GameButton>("%Continue").Pressed += OnContinue;
GetNode<GameButton>("%NewGame").Pressed += OnNewGame;
GetNode<GameButton>("%Quit").Pressed += OnQuit;
}
// TODO: figure out why Godot successfully changes the scene but *also* throws a "data.tree" is null error,
// even though this is being triggered by a UI Button's "Pressed" signal (not a physics anything).
private void OnContinue() {
GetTree().ChangeSceneToFile(ContinueScene);
}
private void OnNewGame() {
GetTree().ChangeSceneToFile(NewGameScene);
} Regardless, this is a super confusing error - one would expect the "simple" mechanism of changing a scene, a function named |
Same here. When pressing the "start" button on the main menu in my game (pressed signal), I call And it works, but also throws two "data.tree is null" errors. If I use call_deferred, it still throws the errors. This didn't use to happen, and I haven't changed anything in the main menu, so I have no idea what started it, but I can't find a way to get rid of the errors. |
Tested versions
Reproducible in: 4.2 stable
System information
Win 10, Godot 4.2 stable, Forward +, dedicated Nvidea RTX 1080
Issue description
Edit: currently recommend workaround/fix seems to be to call
change_scene_to_file()
deferred.So instead of
write:
Original issue description:
Using
get_tree().change_scene_to_file("res://some_scene.tscn")
works , but it produces a number of red errors. These seem to be different depending on the circumstances.To test this, I made two scenes, Scene A and Scene B using Area3Ds and CharacterBody3D (with default template script):
In Scene A I change scene by walking into an Area3D with a CharacterBody3D (template script), triggering a
body_entered
signal:This will produce these two errors:
In Scene B I change scene by walking into an Area3D with a CharacterBody3D, triggering a
body_entered
signal which will set acan_interact
boolean variable in the character script. If the player then presses an Input action, the character fires a global custom signal, which the level connects to and changes the scene:Global Autoload:
Character:
Level:
This will produce these four errors:
Note: Line 34 in the character script is just
move_and_slide()
Possibly related issue (however that's a different error): #84681
Steps to reproduce
Use
get_tree().change_scene_to_file("res://some_scene.tscn")
as described above, or test the provided Minimal Reproduction Project below.Minimal reproduction project (MRP)
change_scene_errors.zip
The text was updated successfully, but these errors were encountered: