Attempt to call function 'set_radius' in base 'null instance' on a null instance

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By joaquin-montesdeoca

Ok, I’ve created a Ball scene which is composed of a Circle2D scene which can be modified to set a radius to it.

At the same time I’ve created a GravityCenter Area2D whose radius can be changed as well.

This is the structure of the scene.

And this is the code of the Ball scene:

extends RigidBody2D
class_name Ball
tool

export (float) var radius_ball = 10.0 setget set_radius_ball, get_radius_ball
export (float) var radius_gravity_area = 50.0 setget set_radius_gravity_area, get_radius_gravity_area

onready var circle2d : Circle2D = $Circle2D
onready var gravity_center : GravityCenter = $GravityCenter

func _ready() -> void:
	apply_radius_ball()
	apply_radius_gravity_area()

func set_radius_ball(value : float) -> void:
	radius_ball = value
	if is_instance_valid(circle2d):
		apply_radius_ball()

func apply_radius_ball() -> void:
	circle2d.set_radius(radius_ball)

func get_radius_ball() -> float:
	return radius_ball

func set_radius_gravity_area(value : float) -> void:
	radius_gravity_area = value
	if is_instance_valid(radius_gravity_area):
		apply_radius_gravity_area()

func apply_radius_gravity_area() -> void:
	gravity_center.set_radius(radius_gravity_area)

func get_radius_gravity_area() -> float:
	return radius_gravity_area

At the moment I instance the scene

var ball : Ball = Ball.new()
ball.global_position = ball_position.global_position
		
owner.add_child(ball)

Then I get an error in line

circle2d.set_radius(radius_ball)

That says:

Attempt to call function 'set_radius' in base 'null instance' on a null instance

I understand this happens when the node isn’t found, but should I instance this node in a different way so that it instances its own children? As far as I know, this calls first the _ready function so it should have already instanced the scene children.

I don’t really know the right answer but I get something I couldn’t understand.
This is only trying to help you, and I probably don’t know everything, but this line as something wrong (or do I misunderstand) :

onready var circle2d : Circle2D = $Circle2D

So circle2d seems to be a “type” of Node2D (this is what I see in the structure of the scene)
But you try to set circle2d with a “type” of Circle2D : is it a custom type class_name?
It will help to see the Circle2D script code

If you need a CircleShape2D, for setting the radius, it is simple as :

circle2d.radius = radius_ball

I’m wondering why you need another scene for this, also you already have a CollisionShape2D (the CircleShape2D should be set here in the editor)

Please avoid using type return in your function, when there’s no need, it make things more complex for nothing : (here an example of a function in my dev, we don’t care about what it return, because wee just call it)

func jump_action(amount:float):
	state.eval.jumping = true
	motion.y = -amount*range_lerp(speed,0,1,0.7,1.0)
	jump_release = motion.y

Luck_437 | 2020-04-14 20:08

Hi, thanks for your answer.

Circle2D is effectively a Node2D whose only purpose is to draw a circle in its position. I thought I’d make it nice and configurable from the outside and be able to set its radius through the method set_radius.

Maybe I should just draw the circle from the Ball class instead of trying to be fancy.

This is the Circle2D code:

extends Node2D
class_name Circle2D
tool

export (float) var radius = 10.0 setget set_radius, get_radius

func _ready() -> void:
	var a = 5
	pass

func set_radius(value : float) -> void:
	radius = abs(value)
	update()

func get_radius() -> float:
	return radius

func _process(delta: float) -> void:
	update()

func _draw() -> void:
	draw_circle(Vector2.ZERO, radius, modulate)

Nothing fancy.

The reason I made this object was to have a shape node, since the CircleShape2D’s purpose is to serve as a collision shape. So I wanted to create a node whose only purpose was to draw a shape.

Please avoid using type return in your function, when there’s no need,
it make things more complex for nothing

I don’t know what do you mean here, I’m only using return in getter methods.

joaquin-montesdeoca | 2020-04-14 22:51

Okay why not, I understand you should not using the rigidbody scale to avoid messing up with the physics engine.

Do you still get your error “null instance” ?
I think circle2d is null you could try to print(circle2d) in ready, it should tell you “Node2D”.
It’s absurd but try without type catch in your ball script :

onready var circle2d = $Circle2D

What I would do, is to think simple at first and try to code everything inside the Ball script.
At the end of the world, there is only draw() and update() involve (not sure update is a necessery but it’s not a matter here).
Also I’m wondering, isn’t the radius_gravity_area proportional from the radius_ball ?
I understand the tool behavior you need to quickly visualize your intial steps, it’s still possible, but sometimes it mess up the code execution (when there is an error), and there isn’t anything you could do for knowing exactly what is wrong.

Don’t let misunderstood things, if needed send me your project, I will try to resolve if you want.

Luck_437 | 2020-04-15 10:36