Godot Version
Godot v4.7.2.stable
Question
What’s a better implementation of referring to possibly non-existant child nodes that doesn’t cause errors?:
To implement different player weapons I’ve got a weapon class extending Node2D.
Each new weapon is its own scene with a weapon node (or node inheriting from weapon) at its root.
Each weapon scene has its own sprite and whatever other children, including a specific Marker2D and/or an AnimationPlayer which the base weapon class refers to, but these are optional.
I have these declared as @onready variables in the base weapon class, and if they’re null certain code is skipped.
This all works fine so far but I’m wondering if there’s a more proper way of referring to these not necessarily extant nodes (once, I know using the $Reference is more expensive) without the debugger throwing errors.
class_name Weapon extends Node2D
@export var weapon_stats : WeaponStats
@onready var gun_barrel: Marker2D = $GunBarrel
@onready var animation_player: AnimationPlayer = $AnimationPlayer
var next_attack = 0
#generic attack, can be overridden for special weapons
func attack() -> bool:
if Time.get_ticks_msec() < next_attack:
return false
#if it's a projectile weapon, make the projectiles
if weapon_stats.projectile_scene != null:
for i in range(weapon_stats.projectiles_per_shot):
var bullet = weapon_stats.projectile_scene.instantiate()
#if a GunBarrel Marker2D is omitted, spawn in the middle of the entity
if gun_barrel != null:
bullet.global_position = gun_barrel.global_position
bullet.global_rotation = gun_barrel.global_rotation
else:
bullet.global_position = global_position
bullet.global_rotation = global_rotation
get_tree().current_scene.add_child(bullet)
#re/start attack animation. Animations for weapons are made to last 1 second
#and scaled based on attack speed
if animation_player != null:
animation_player.stop()
animation_player.play("attack", -1, 1000.0/weapon_stats.refire)
next_attack = Time.get_ticks_msec() + weapon_stats.refire
return true
Thanks for reading