The error is telling you that there isn't a game_started
defined in the parent node. There is a parent node, but it does not have a property game_started
defined.
You probably intended it to be a property, but you forgot to define it, defined it somewhere else, or you did define it in the correct place, but instanced the node under the wrong parent. However, it is also possible you made it a method and simply forgot ()
. I don't know which is the case.
Regardless, in Godot, a common design pattern is to access down and signal up the scene tree. In this case, you are trying to access up the scene tree. This is problematic because the scene can't ensure where it will be instanced.
I'll give you a few approaches to solve this problem:
Check if game_started
exists.
The change that will have a smaller impact on your architecture is to check if the parent node has game_started
before trying to read it. Which looks something like this:
var parent = get_parent
if !"game_started" in parent or !parent.game_started:
return
However please notice that even if this gets rid of the error, it is not fixing the source of the problem. Since game_started
is not defined in the parent anyway.
Furthermore, _physics_process
is still getting called. There are ways to don't even have the call, which is better for performance. Will come back to that.
Let the parent access the child.
What you want to accomplish is to enable and disable _physics_process
based on the value of game_started
. There is a way to enable and disable _physics_process
in the engine: set_physics_process
.
Presumably there is some other code somewhere that sets game_started
on the parent, in that moment it could call set_physics_process
on the child to disable or enable _physics_process
accordingly.
You may even use a property (with setget
) to this effect.
For example:
var game_started:bool setget set_game_started
func set_game_started(new_value:bool) -> void:
if game_started == new_value:
return
for child in get_children():
child.set_physics_process(new_value)
game_started = new_value
With this, your script does not have to check game_started
. One drawback is that the code only uses set_physics_process
on the direct children. We could write a recursive version, however, we can do better!
Use pause.
As you can see in pausing games, you can use get_tree().paused
to get or set if the game is paused. Which will stop _physics_process
(among other methods) depending on the pause_mode
.
Thus, you can have the parent update get_tree().paused
...
Assuming, you also want a pause, you may follow this pattern:
var game_started:bool setget set_game_started
var game_paused:bool setget set_game_paused
func set_game_started(new_value:bool) -> void:
game_started = new_value
update_pause()
func set_game_paused(new_value:bool) -> void:
game_paused = new_value
update_pause()
func update_pause() -> void:
get_tree().paused = !game_started or game_paused
Then, for the nodes that should still work when the game is paused or not started, you can se pause_mode = PAUSE_MODE_PROCESS
so they don't get _physics_process
et.al. disabled. Then they can check game_started
and game_paused
to distinguish if the game is paused or not started.
A drawback is that this will affect nodes everywhere… If only game_started
and game_paused
could be available everywhere… Well, we can do that too!
Use an autoload.
Make an autoload (via project settings) of a scene with a node that has game_started
et.al. So that it is available from everywhere. Then you can access it from everywhere.
You can do this combined with the paused
as explained above. Which is what I would recommend.
Alternatively. Since you can access it from everywhere, you you could simply access it instead of the parent:
if !autoload_name.game_started:
return
This is the exception to the access down and signal up rule. Since the autoload is available everywhere and it does not depend on where or how the scene was instanced.
I remind you, is that paused
and set_physics_process
will avoid the call to _physics_process
, and thus are more performant than checking this way.