Invalid assignment of property or key 'visible' with value of type 'bool' on a base object of type Nil

Godot Version

v4.4.1-stable

Question

I have this problem where whenever I start the game the Game manager (which is going to be the game global variables and signals manager) sends a signal to hide the Area_P object which is a Area2D which contains a CollisionShape2D and a Sprite2D. It does so by when the signal is received by area_P, it will inside its own script acess the property visible of the two child nodes and try to hide them. Problem is, as stated in the title, it returns an error because the two variables I declare to reference the child nodes of Area_P are null for some reason. Is there a better way to do what Im doing and most importantly, why is this error occurring in the first place? I tried looking for other topics on this on the forum but due to my inexperience I think (at least) some of them arent related or I cant make out whats wrong in their case


I’m not sure where the script actually is, but it’s not attached to the Area2D node. There would be an icon next to it in the Scene tab indicating a script was attached if it were.

Hi!

One issue you may have is that the signal is emitted on manager.gd ready, while the area_2d.gd variables are also set on ready (using the onready technique). Depending on the order of the ready calls, those variable may just not be initialized yet.

In the _on_manager_startup_hide_all() function, try to set your variables, and see if it works.
Like this:

area_hitbox = $AreaHitbox
area_sprite = $AreaSprite
area_hitbox.visible = false
area_sprite.visible = false

And then you can change the nodes structure to fix the order of ready calls, or just remove the onready assignments and do it another way. To avoid setting the variables each time the signal is triggered, you can also check if they are null, like this:

if area_hitbox == null:
    area_hitbox = $AreaHitbox

Let me know if that helps!

1 Like

On top of the answers you got already, you are breaking the unwritten rule “call down, signal up”
There isn’t really a need to emit that signal from your global manager. Your manager should have access to Area_P directly and therefore should be calling into a function area_p.hide_all().
This is going to mean a design shift but you should to do it anyway since autoloads are always loaded first. No non-global nodes will be ready in that globals _ready() function.

1 Like

The script is attached to the Area_P node which is a Node which is not shown here but is like the parent node of Area2D and AreaHitbox and AreaSprite

Is this the correct way?


*just a heads up I renamed the signal to toggle but it works almost the same basically

Combining all your answers about breaking the call down signal up rule and the onready problem I made these modifications:




It seems to have solved the issue but I’m still not 100% how the problem with onready is solved, when I use a variable that is initialized with @onready, I need to do
"if variable == null:
variable = $path
to always solve it? Or theres a better way to solve this issue?

do not use null.

the correct way is

if area_hitbox:

or

if is_instance_valid(area_hitbox):

and avoid using !, use not instead.

this code is mostly completely useless.
hiding a node will hide its children, and using onready already sets the references. setting references should not be done from a function connected to a signal unless it’s obtaining a new Node.

extends Area2D

@onready var area_hitbox : CollisionShape2D = $AreaHitbox
@onready var area_sprite : Sprite2D = $AreaSprite

func _on_toggle() -> void:
	visible = not visible

edit: if you need to hide everything at start… just set it to not visible in the editor

I see thanks for the tips everything is so confusing as a beginner so I didnt really know how setting the visible at the start or disabling it works but now I think everytime I need Area_P to appear again I will just call the toggle function in manager. Also is the “!” operand not useful for booleans in godot or is it just in this specific case ?

! works in godot but it’s there so people coming from other languages can have an easier time when they are starting.

the godot style guide calls for the use of not because it’s better for readability.
it also has some neat features like being able to do:

if my_node is not Node2D:

and the usage of null has some complications, the short story is that it doesn’t always work due to internals of the godot engine. also readability.

1 Like