![]() |
Attention | Topic was automatically imported from the old Question2Answer platform. |
![]() |
Asked By | Jack_Aplex |
I was following a tutorial on Youtube about making a 3d top down shooter. Whenever I try to click to shoot my game crashes and I get the error
Attempt to call function ‘shoot’ in base ‘null instance’ on a null instance.
this is the code I have. this isn’t my own original code.
extends KinematicBody
onready var gun_controller = $guncontroller
var speed = 8
var velocity = Vector3()
func _process(delta):
#movement
velocity = Vector3()
if Input. is_action_pressed("ui_right"):
velocity.x -= 1
if Input. is_action_pressed("ui_left"):
velocity.x += 1
if Input. is_action_pressed("ui_up"):
velocity.z += 1
if Input. is_action_pressed("ui_down"):
velocity.z -= 1
velocity = velocity.normalized() * speed
move_and_slide(velocity)
if Input.is_action_pressed("primary_action"):
gun_controller.shoot()
its saying the error is from the last line of code above. just incase it is needed also Im putting the code for the gun controller and gun itself.
gun controller code
extends Node
export(PackedScene) var StartingWeapon
var hand :Position3D
var equipped_weapon : Spatial
func _ready():
hand = get_parent().find_node(“hand”)
if StartingWeapon:
equip_weapon(StartingWeapon)
func equip_weapon(weapon_to_equip):
if equipped_weapon:
print(“Deleting current weapon”)
equipped_weapon. queue_free()
else:
print(“No weapon equipped”)
equipped_weapon = weapon_to_equip. instance()
hand.add_child(equipped_weapon)
func shoot():
if equipped_weapon:
equipped_weapon.shoot()
Gun Code
extends Spatial
export(PackedScene) var bullet
onready var rof_timer = $Timer
var can_shoot = true
export var muzzle_speed = 30
export var millis_between_shots = 100
func _ready():
rof_timer.wait_time = millis_between_shots / 1000.0
func _process(delta):
pass
func shoot():
if can_shoot:
var new_bullet = bullet.instance()
new_bullet.global_transform = $muzzle.global_transform
new_bullet.speed = muzzle_speed
var scene_root = get_tree().get_root().get_children()[0]
scene_root.add_child(new_bullet)
print(“pew”)
can_shoot = false
rof_timer.start()
Lastly Im posting the line to the tutorial I was using so if anyone needs an better idea of how it works
Umm… Sorry, this is a bit confusing for me. Mind sharing the tutorial? Or even sharing the project via a google drive link would help a lot.
I do notice that your function ‘shoot()’ is not in the same script as your KinematicBody2d. For you KinematicBody2D script to access that particular function, you have to have them in the same script. (I’m not sure if this is the problem though. Like I said before, having access to the project itself would really help a lot)
Assuming you’re not sure how to access functions from different scripts, you just need to get the node.
If both your nodes’ have the same parent, all you need to do is: get_parent().get_node(node name).shoot()
If your gun_controller node is a child under the KinematicBody2D (meaning KinematicBody = parent and gun_controller = child), then you can just
get_node(node name).shoot()
or
get_child(0) *based on index number. In gdscript, the first number is 0, second number is 1, and so on.
If your gun_controller node is not under the same parent, you can use an absolute path.
get_node(“…/Node2D/gun_controller”).shoot()
absolute paths can be used anytime, though I find them finnicky and bothersome. I would only use them if I have to, as I rearrange nodes all the time. The ‘…’ before the path is something you should put first everytime you want to use an absolute path.
And there we go. Sorry for the long (and extremely confusing) comment. If you want, you can add a link to a google drive file, and I can take a closer look.
TheJokingJack | 2021-05-25 01:37