My node isn't recocnising it has children i think

4.3

my Bow node, a child of my player scene is saying “attempt to call function ‘start’ in base ‘null instance’ on a null instance” when i try to call on the Power_timer node which is a child of it

my code is :

extends Node2D

var shootable = true
@onready var bullet_path = preload("res://Scenes/Arrow.tscn")
@onready var player_path = preload("res://Scenes/Player.tscn")
@onready var Shoot_line = self.get_node("/root/Bow/Shoot_guide")
@onready var Shoot_point = self.get_node("/root/Bow/Shoot_point")
@onready var Power_timer = self.find_child("Shoot_timer")
var power:float

func _ready():
	pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	look_at(get_global_mouse_position())
	if Input.is_action_just_pressed("shoot"):
		Power_timer.start()
		pass
	if Input.is_action_just_released("shoot"):
		Power_timer.stop()
		fire()

func fire() :
	if shootable == true:
		var bullet = bullet_path.instantiate()
		var player = player_path.instantiate()
		bullet.dir = rotation + 3.14159265
		bullet.pos = Shoot_point.global_position
		bullet.rota = global_rotation
		get_parent().add_child(bullet)
		power = 0


func _on_shoot_timer_timeout():
	power += 10
	Power_timer.start()

my node layout is
player
-collisionshape2d
-camer2d
-ui
–coordinates
–fps
–gravity
–bow_power
-animatedsprite2d
-bars
–power_progress_bar
-bow
–shoot_point
–shoot_guide
–shoot_timer

help pls

This path is strange, seems to imply you’ve added the Bow as a global in addition to as a child of your player

@gertkeno i did so i can refrence the power variable in the player script for the “bow_power” label node

Globals make a new node under /root/ that is in no way tied to your child node, they are two separate nodes with separate values.

Instead of using self.get_node you can use the $ shorthand to get children and access their variables.

@onready var Shoot_line = $bow/shoot_guide
@onready var Shoot_point = $bow/shoot_point
@onready var Power_timer = $bow/shoot_timer

i did that and removed ‘Bow.gd’ from globals and it still gave me the same error

Can you share your actual scene tree? you can paste the results of print_tree_pretty() if you don’t want to screenshot the Scene tab.

╴Player
┠╴CollisionShape2D
┠╴Camera2D
┠╴UI
┃ ┠╴Coordinates
┃ ┠╴FPS
┃ ┖╴gravity
┠╴Bars
┃ ┖╴Power_progress_bar
┠╴Bow
┃ ┠╴Shoot_point
┃ ┠╴Shoot_guide
┃ ┖╴Shoot_timer
┖╴AnimatedSprite2D

Ah so did you capitalize the paths correctly in code? i.e.

@onready var Shoot_line = $Bow/Shoot_guide
@onready var Shoot_point = $Bow/Shoot_point
@onready var Power_timer = $Bow/Shoot_timer

i didn’t but just did and is still not working btw thanks for helping

Is there any reason another script would delete the timer? What does your new script look like with all the changes?

no i dont think so, ive removed all refrences to the bow script since i removed “bow.gd” from globals and
extends Node2D


var shootable = true
@onready var bullet_path = preload("res://Scenes/Arrow.tscn")
@onready var player_path = preload("res://Scenes/Player.tscn")
@onready var Shoot_line = $Bow/Shoot_guide
@onready var Shoot_point = $Bow/Shoot_point
@onready var Power_timer = $Bow/Shoot_timer

var power:float

func _ready():
	pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	look_at(get_global_mouse_position())
	if Input.is_action_just_pressed("shoot"):
		Power_timer.start()
		pass
	if Input.is_action_just_released("shoot"):
		Power_timer.stop()
		fire()

func fire() :
	if shootable == true:
		var bullet = bullet_path.instantiate()
		var player = player_path.instantiate()
		bullet.dir = rotation + 3.14159265
		bullet.pos = Shoot_point.global_position
		bullet.rota = global_rotation
		get_parent().add_child(bullet)
		power = 0


func _on_shoot_timer_timeout():
	power += 10
	Power_timer.start()

Personally, rather than using a timer I’d probably just use an accumulation var with delta:


const SHOOT_TICK      = 1.0
const POWER_INITIAL   =  5
const POWER_INCREMENT = 10

var shoot_time: float
var power:      int

func _process(delta: float) -> void:
    if Input.is_action_just_pressed("shoot"):
        shoot_time = delta
        power      = POWER_INITIAL
    elif Input.is_action_pressed("shoot"):
        shoot_time += delta
        if shoot_time >= SHOOT_TICK:
            power      += POWER_INCREMENT
            shoot_time -= SHOOT_TICK

    if Input.is_action_released("shoot"):
        fire(power)

And you removed the global version? Try adding print(get_path()) to the _ready function

@hexgrid i did that and now its having issues with the other refrences to its children

@gertkeno the output of that is /root/Main/Player/Bow

thank you guys so much, i finaly fixed it with this script:

extends Node2D

const SHOOT_TICK = 0.5
const POWER_INITIAL = 0
const POWER_INCREMENT = 10

@onready var bullet_path = preload("res://Scenes/Arrow.tscn")
@onready var player_path = preload("res://Scenes/Player.tscn")
@onready var Shoot_point = $Shoot_point
@onready var Power_timer = $Bow/Shoot_timer

var shootable = true
var power : float
var shoot_time : float

func _ready():
	print(get_path())
	$AnimatedSprite2D.play("first")


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	look_at(get_global_mouse_position())
	
	if Input.is_action_just_pressed("shoot"):
		shoot_time = delta
		power = POWER_INITIAL
	elif Input.is_action_pressed("shoot"):
		shoot_time += delta
		if shoot_time >= SHOOT_TICK :
			power += POWER_INCREMENT
			shoot_time -= SHOOT_TICK
	if Input.is_action_just_released("shoot"):
		fire()
	if power <= 125:
		$AnimatedSprite2D.play("first")
	elif power <= 250:
		$AnimatedSprite2D.play("second")
	elif power <= 375:
		$AnimatedSprite2D.play("third")
	elif power <= 500:
		$AnimatedSprite2D.play("fourth")
	
	$Label.text = var_to_str(power)
	if Input.is_action_just_pressed("fill"):
		power += 20
	
	if power >= 500:
		power = 500

func fire() :
	if shootable == true:
		var bullet = bullet_path.instantiate()
		var player = player_path.instantiate()
		bullet.dir = rotation + 3.14159265
		bullet.pos = Shoot_point.global_position
		bullet.rota = global_rotation
		#bullet.speed = power
		get_parent().add_child(bullet)
		power = 0

and this tree :
Player
┠╴CollisionShape2D
┠╴Camera2D
┠╴UI
┃ ┠╴Coordinates
┃ ┠╴FPS
┃ ┖╴gravity
┠╴Bars
┃ ┖╴Power_progress_bar
┠╴AnimatedSprite2D
┖╴Bow
┠╴Shoot_point
┠╴AnimatedSprite2D
┖╴Label

1 Like