Reputation: 1
i'm using this tutorial on youtube(https://www.youtube.com/watch?v=pgMiiUSRvSM&t=1304s) to make an fps shooter game in godot and i'm quite new to it when i tried to run the script i have an error in the weapon_manager.gd script saying, Attempt to call function 'update_weapon_ui, in base 'null instance' on a null instance
this is the screenshot of my node tree that this script is attached to enter image description here
extends Spatial
# All weapons in the game
var all_weapons = {}
# carrying weapons
var weapons = {}
# HUD
var hud
var current_weapon
var current_weapon_slot = "Empty"
var changing_weapon = false
var unequipped_weapon = false
var weapon_index = 0
func _ready():
hud = owner.get_node("HUD")
all_weapons = {
"Unarmed" : preload("res://weapons/Unarmed.tscn"),
'Pistol' : preload("res://weapons/Pistol.tscn"),
"Rifle" : preload("res://weapons/Rifle.tscn")
}
weapons = {
"Empty" : $Unarmed,
"Primary" : $Rifle,
"Secondary" : $Pistol
}
# Initialize references for each weapons
for w in weapons:
if weapons[w] != null:
weapons[w].weapon_manager = self
weapons[w].player = owner
weapons[w].visible = false
# Set current weapon to unarmed
current_weapon = weapons["Empty"]
change_weapon("Empty")
# Disable process
set_process(false)
# Process will be called when changing weapons
func _process(delta):
if unequipped_weapon == false:
if current_weapon.is_unequip_finished() == false:
return
unequipped_weapon = true
current_weapon = weapons[current_weapon_slot]
current_weapon.equip()
if current_weapon.is_equip_finished() == false:
return
changing_weapon = false
set_process(false)
func change_weapon(new_weapon_slot):
if new_weapon_slot == current_weapon_slot:
current_weapon.update_ammo() # Refresh
return
if weapons[new_weapon_slot] == null:
return
current_weapon_slot = new_weapon_slot
changing_weapon = true
weapons[current_weapon_slot].update_ammo() # Updates the weapon data on UI, as soon as we change a weapon
update_weapon_index()
# Change Weapons
if current_weapon != null:
unequipped_weapon = false
current_weapon.unequip()
set_process(true)
# Scroll weapon change
func update_weapon_index():
match current_weapon_slot:
"Empty":
weapon_index = 0
"Primary":
weapon_index = 1
"Secondary":
weapon_index = 2
func next_weapon():
weapon_index += 1
if weapon_index >= weapons.size():
weapon_index = 0
change_weapon(weapons.keys()[weapon_index])
func previous_weapon():
weapon_index -= 1
if weapon_index < 0:
weapon_index = weapons.size() - 1
change_weapon(weapons.keys()[weapon_index])
# Update HUD
func update_hud(weapon_data):
var weapon_slot = "1"
match current_weapon_slot:
"Empty":
weapon_slot = "1"
"Primary":
weapon_slot = "2"
"Secondary":
weapon_slot = "3"
hud.update_weapon_ui(weapon_data, weapon_slot)
i tried to rewatch the tutorial and see what i miss but it didn't work i don't understand why this has an error
Upvotes: 0
Views: 103
Reputation: 40315
The error is telling you that hud
is null
, which means that the following line failed:
hud = owner.get_node("HUD")
You should also get an error about that.
That failed because isn't a node called HUD
as direct child of the root of the edited scene that has the node that the shown script attached.
To clarify, owner
is the root of the edited scene (Player
in this case). And get_node("HUD")
is looking for a direct child with the name
property set to "HUD"
.
I'll give you three solution from more efficient to less efficient.
The first solution is to move HUD
so it is a direct child of Player
. Then the following line should work:
hud = owner.get_node("HUD")
A variant of this would be to use the fixed path for the current location of HUD
instead of moving HUD
. Then you need this code:
hud = owner.get_node("Camroot/HUD")
Notice that the parameter of get_node
is the path to get to the node you want in the scene tree.
The second solution is to use Scene Unique Nodes. To do that open the context menu on HUD
on Scene, and select "% Access as Unique Name". That will allow you to get it like this:
hud = owner.get_node("%HUD")
Yet another option is to export a NodePath
:
export var hud_path:NodePath
Which you can set to the correct node in the inspector. And then you do this to retrieve it:
hud = owner.get_node(hud_path)
A wildly different approach to do this is by adding the HUD
to a node group, which you can do in the Node panel Groups tab. For example if it is in the "hub"
you could do this:
hud = get_tree().get_nodes_in_group("hub")[0]
Notice that this is not limited to the currently edited scene, and also that it get_nodes_in_group
gives us an array and with [0]
I'm getting the first element (assuming there is one). A more proper usage would get the array and check if it is empty.
As you can imagine, node groups work better if you are interested in a, well... group of nodes, instead of a single one.
The third solution is to use find_node
:
hud = owner.find_node("%HUD")
Then it will iterate over all the nodes in the scene until it finds one called "HUD"
.
Upvotes: 0