Help Shooting Bullet

Godot Version

4.2.2

Question

I am working on a Bullet Hell Rougelite game, and I am trying to allow the player to shoot bullets. But every time I shoot it throws an error
Invalid call. Nonexistent function ‘instance` in base ‘CharacterBody2D (bullet.gd)’

Player
|-Graphics
|-CollisionShape2D
|-Weapon
 |-Bullet
  |-Graphics
  |-CollisionShape2D

weapon.gd

extends Node2D


@export var bullet_speed = 10000

signal shoot_bullet(speed)

func _ready():
    $Bullet.visible = false

func _process(_delta):
    look_at(get_global_mouse_position())

func shoot(speed):
    print(“Shooting Speed: “ + str(speed))
    var bullet_instance = $Bullet
    bullet_instance.rotation = rotation
    var instance = bullet_instance.instance()
    add_child(instance)
    $Bullet.visible = true
    shoot_bullet.emit(bullet_speed)

func _input(_event):
   if Input.is_action_just_pressed(“attack”):
       shoot(bullet_speed)

bullet.gd

extends CharacterBody2D


func _physics_process(_delta):
    move_and_slide()

func _on_weapon_shoot_bullet(speed, delta):
    look_at(get_global_mouse_position())
    var move_vec = Vector2(speed, 0).rotated(rotation)
    global_position += move_vec * delta

instantiate() is the function name now, changed in Godot 4.0

1 Like

@gertkeno thanks, but whenever I shoot it throws this error though (similar to the one I provided in the OP) → Invalid call. Nonexistent function ‘instantiate’ in base ‘CharacterBody2D (bullet.gd)’

You can’t instantiate a node, you’re probably looking for duplicate

2 Likes

@athousandships I know this would be not on topic, but when I shoot, it doesn’t face and move in the right way (the opposite way in fact), and the movement doesn’t repeat. How could I fix this?

You will want instantiate(), but you need to re-organize a couple things first.

Typically the bullet should not exist until fired, right click “Bullet” in the scene tree and select “Save Branch as Scene”, name it “Bullet.tscn”, then delete it from the Player’s scene. In your script you will reference and instantiate this new scene like so.

# weapon .gd
extends Node2D

const BULLET = preload("Bullet.tscn")
@export var bullet_speed = 10000

func shoot(speed):
    var bullet_instance = BULLET.instantiate()
    # adding as a child ment moving the player moves any bullets
    # in flight too so we add child to the root instead
    get_tree().root.add_child(instance)

The bullet only needs it’s _physics_process if we supply the rest of the information at instantiation.

func shoot(speed):
    var bullet_instance = BULLET.instantiate()
    bullet_instance.position = global_position
    var brotation := (get_global_mouse_position() - global_position).angle()
    bullet_instance.rotation = brotation # make negative if your image is facing left
    bullet_instance.velocity = Vector2(bullet_speed, 0).rotated(brotation)
    get_tree().root.add_child(instance)
1 Like

@gertkeno I get an error of Parser Error: Cannot find member “visible” in base “PackedScene”

I used everything you had and I change where it said $Bullet to BULLET.

any line with BULLET.visible = is to be deleted, don’t need to change the visibility of something that doesn’t exist yet.

1 Like

Now I am getting Invalid call. Nonexistent function ‘instantiate’ in base ‘CharacterBody2D (bullet.gd)’

weapon.gd

extends Node2D


@export var bullet_speed = 10000
const BULLET = preload(“res://bullet.tscn”)

signal shoot_bullet(speed)

func _ready():
    pass

func _process(_delta):
    look_at(get_global_mouse_position())

func shoot(speed):
    var bullet_instance = BULLET.instantiate()
    var instance = bullet_instance.instantiate()
    bullet_instance.position = global_position
    var rotation := (get_global_mouse_position() - global_position).angle()
    bullet_instance.rotation = rotation
    bullet_instance.velocity = Vector2(bullet_speed, 0).rotated(rotation)
    get_tree().root.add_child(instance)
    shoot_bullet.emit(speed)
    
func _input(_event):
    if Input.is_action_just_pressed(“attack”):
        shoot(bullet_speed)

bullet.gd

extends CharacterBody2D


func _ready():
    visible = true

func _physics_process(_delta):
    move_and_slide()
func shoot(speed):
    var bullet_instance = BULLET.instantiate()
    #var instance = bullet_instance.instantiate() # do not instantiate an instance
    bullet_instance.position = global_position
    var rotation := (get_global_mouse_position() - global_position).angle()
    bullet_instance.rotation = rotation
    bullet_instance.velocity = Vector2(bullet_speed, 0).rotated(rotation)
    get_tree().root.add_child(bullet_instance)
    shoot_bullet.emit(speed)
1 Like