Problem with "cannot call the method 'change_to_file' on a null value"

Godot Version

4.2

Question

Hi everyone, I’m new to Godot. I am currently working on a school project that is extremely important to me. if I were not able to complete it I would also make the work of my team useless.

Our project is a first-person point and click game (like rusty like games). There are several scenes, each with their own areas 2d. Each area2d has different effects, and some of these, if clicked, take you to other scenes. This image is an example of a typical scene from my game:

the 2d areas that are on the doors and at the bottom of the screen take you to other scenes. The whole scene is managed by a script, which manages the various clicks made on the scene. For example, the following image is a part of the script for this scene, which manages the transitions from this scene to another when I click on areas 2d (if you need images of the entire script I will attach them without problems):

Now: The problem I’m currently having concerns change_scene_to_file(), basically it sometimes (pretty rarely) crashes with the error: “cannot call the method ‘change_to_file’ on a null value”. Searching online I understood that it is an error that happens when the script is asked to change multiple scenes at the same time, in my example double clicking in the back area (i.e. the 2d area below) or in the doors areas (the one on the left, and the one on the front) would generate a crash due to the fact that the scene tries to change twice, but the second time fails because get_tree() returns null.
The point is that when I start the transition with the

TransitionScreen.transition()

a ColorRect appears on the screen which, from what I can see, blocks mouse input. So basically during the:

await TransitionScreen.on_transition_finished

the mouse inputs should be blocked.
Below I attach the image of the transition_screen scene and the related script

However, yesteday i noticed that this crash occures every time I:

  • Keep the right mouse button pressed
  • Click on the area2d that bring me to another scene with the left mouse button (keeping the right mouse button pressed)
  • Click another time on the same area2d (keeping the right mouse button pressed)

So somehow holding down an input nullifies the effect of ColorRect and allow me to double click the area while the fade in/out effect of the transition script is running (basically during the await).
As I said, the game crashes every time this is done, however I’m not one hundred percent sure that this is the only behavior that can negatively affect the scene change, and honestly I have no idea how to understand exactly what generates the error Cannot call the method ‘change_to_file’ on a null value

What I tried:

Yesterday, noticing this behavior, and following some advice given to me on discord, I tried to insert a change to the scene script, here’s what it consists of:

That boolean is a variable that is setted to false when the transition animation is ended (you can see it in the transition_scene script).
So, this seems to resolve the issue of keeping the right mouse button pressed while clicking with the left mouse button, but i have still some doubts

What i need to know:

do you think that checking that boolean can actually completely eliminate crashes due to double recorded input? Is there a safer solution? Im so desperate because i don’t know if every time the project has crashed with the error “cannot call the method ‘change_to_file’ on a null value” was because i misclicked the right mouse button while pressing the left one.

As i said this project is really important to me. If anyone is available, a call on discord is also ok for me so that I can explain the project more completely

A quick and dirty hotfix would be to simulate the right mousebutton unpressing whenever the area2d is clicked with the left mouse button? In that case, we forcibly unclick the right mousebutton by code.

var a = InputEventMouseButton.new()
a.position = get_global_mouse_position()
a.button_index = MOUSE_BUTTON_RIGHT
a.pressed = false
Input.parse_input_event(a)

If this doesn’t work, then we need to analyze the moment the game crashes and review the code procedure up until the crash.
I am personally not a fan of directly changing scenes so this is a bit outside my expertise.

The boolean check should suffice as you will only be able call the function once, locking out any other inputs such as the right click.

It is exactly the solution I would of recommended. Have a bool transitioning set to false. Check if !transitioning before your logic. Set to true then perform logic. Set back to false after you have loaded the new scene.

thanks for the reply, I will do some testing.
Btw, does this type of code block input for the entire project (all scenes currently present) or does it block input only in the scene where the code is present?

in my case: if I wrote this code in transition script (so every time the fade in/out transition is called which serves to make the scene change smoother) it would also be able to block the inputs of the areas2d of hallway3 (which is the scene in the first screenshot of my original question)?

Thanks for the help,
I will continue testing with this solution.
Btw I also tried to remove the boolean check in some 2d areas, and test the consequences in a build.
To my surprise, I realized that when I generated the “bug” by holding down the right button and clicking several times with the left on the areas2d without the boolean check, the game was not interrupted or crashed, but simply showed an error in the console.exe. This led me to think that the error

cannot call the method ‘change_to_file’ on a null value

it’s not a critical error, but more of a breakpoint of sorts, am I right? (until now I have always used the “editor debugger” which stops when the error appears)

^so this error shows up but the game still run

I would assume my block of code would go at the start of your transition() method as this is the critical point where you really don’t want the player holding down the rightclick button.
You could copy-paste it in and see if this resolves the issue.

What you could also do is deny the transition when your right mousebutton is pressed.
Check if the right mousebutton is pressed and if yes, you return.

if event is InputEventMouseButton and event.pressed and TestingMousePosition.isTransitionRunning == false:
    if event.button_index == MOUSE_BUTTON_RIGHT: 
        return
    if event.button_index == MOUSE_BUTTON_LEFT:
        [do transition code]

thanks again, i will try this other solution.

Btw i tested the first code:

var a = InputEventMouseButton.new()
a.position = get_global_mouse_position()
a.button_index = MOUSE_BUTTON_RIGHT
a.pressed = false
Input.parse_input_event(a)

but the problem with this is that, if i put this at the start of the

func transition

it doesn’t actually block the input for the entire duration of the transition (that is the fade in/out effect). Is there a way to completely block the input of the entire game during the entire transition time?

what happens when you click the right mousebutton? I was under the impression that you specifically created the TestingMousePosition.isTransitionRunning variable to specifically disable mouse inputs once the transition runs.
Do you perhaps have written a custom InputHandler? Or is it written in some _process() method?

thanks again for the reply,

I didnt write a custom input handler (i have no idea how to do it).

Basically

TestingMousePosition.isTransitionRunning

is just a boolean that is setted to true when

func transition()

is called.

It actually doesnt block the input via code in any way but it makes the ColorRect inside the Transition_screen scene visible which (at least from my understanding) should block the mouse input (since his Mouse Filter is setted to false).

this is the video i got the code of the transition from: https://www.youtube.com/watch?v=Shj_QVwrefY

I use

TestingMousePosition.isTransitionRunning

just as a check. because, as i said, i noticed that, even with the ColorRect visible, some inputs are taken (at least, if im keeping the right mouse button or the mouse wheel pressed while i click again with the left mouse button)

So taking again the first image as an example:

if i click the left door i go to another scene without problems.
But if i keep the right mouse button (or the mouse wheel) pressed and click at least 2 times with the left mouse button the game return the error:

cannot call the method ‘change_to_file’ on a null value

so i started using the

TestingMousePosition.isTransitionRunning == false:

to check if a transition is already running:

#CLICK ON THE COMMON ROOM DOOR (the left area2d)
func _on_common_room_door_input_event(viewport: Node, event: InputEvent, shape_idx: int) → void:
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT and TestingMousePosition.isTransitionRunning == false:
TransitionScreen.transition()
ChangeCursor.change_into_default_cursor()
SfxManagerScene.PlayWoodenDoor_02()
SfxManagerScene.PlayFootsteps_00()
await TransitionScreen.on_transition_finished
get_tree().change_scene_to_file(“res://FirstLevel/CommonRoom/Scenes/CommonRoom.tscn”)

And it seems to work but, as i said in the original question, I’m not sure if it can work in all cases.

btw, the right mouse button should have no consequences, since all interactions in the game are done with the left mouse button (or with the spacebar). i think that the only thing the right mouse button triggers are the on_area_2d_input_event that are inside the scenes scripts, like the one above.

but again, it should be blocked instantly by the first “if” that verify that the input is a left mouse button (and not for example, the right mouse button or the mouse wheel)

so, is there a better way to block all mouse input while the transition is running?

Thanks for the clarification.
Did you create a topic on the Discord server “Godot Café” yet or is the project on github? I would like to replicate the problem for myself as this problem may require a more thorough solution than just a hotfix to disable the right mousebutton.

Does the cannot call the method ‘change_to_file’ on a null value error also comes when you repeatedly change scenes back and forth?

Thx you are an angel :pray:

so: i haven’t created a topic on the discord i just asked here and there in godot cafè server.
Btw have the project on github but i have no idea how to pass you the files… can we use google drive?

btw the error, (at least until now) does not comes when i repeatedly change scenes back and forth

If the project is public, then you can send me the github link, or google drive link is also fine. I will take a look at the project, replicate the problem and check on how to solve it

thx, do i need to basically copy all the project files inside the google drive folder right? (except for the .git folder and the .gitignore and.gitattributes i suppose)

Yes, you can also leave out the .godot folder as it’s essentially just a cache.

thanks a lot, tomorrow morning i will send you the link of the drive privately