Enemy shoot at player nothing happens

Godot Version

`Godot.V4,3

Question

`
I have a problem. The enemy shoots at me only once when starting the game. It also the bullet enemy plays alone when I hit run play game, second problem the enemy bullet don’t hit my player just passing without doing anything to my player health!

How to make my player die after many hits?

Script for player

extends CharacterBody2D

var health = 2

@export var speed = 100
@export var bullet_scene : PackedScene
@onready var sprite_2d: AnimatedSprite2D = $Sprite2d
@onready var bowShoot =$bowShoot
@export var bullet2 : PackedScene
@onready var typhon: AudioStreamPlayer2D = $typhon

func get_input():
	
	var dir = Input.get_axis("back", "forward")
	velocity = transform.x * dir * speed
	if Input.is_action_just_pressed("shoot"):
		shoot()
		bowShoot.play()
		sprite_2d.animation = "shoot"
	if Input.is_action_just_released("shoot"):
		sprite_2d.animation = "idle"
		
	if Input.is_action_just_pressed("shoot2"):
		shoot2()
		typhon.play()
		sprite_2d.animation = "shoot2"	
	
func _physics_process(delta):
	velocity.y += GRAVITY * delta
		
	if Input.is_action_just_pressed("jump"): if not is_on_floor():
		velocity.y = JUMP_FORCE
		sprite_2d.animation = "jump"
	if Input.is_action_just_released("jump"):
		sprite_2d.animation = "idle"
		
		
	move_and_slide()
	
	get_input()
	# Animations
	if Input.is_action_just_pressed("crouch"):
		sprite_2d.animation = "crouch"
	if Input.is_action_just_released("crouch"):
		sprite_2d.animation = "idle"
	
	if Input.is_action_just_pressed("back"):
		sprite_2d.animation = "back"
	if Input.is_action_just_released("back"):
		sprite_2d.animation = "idle"
	
	if Input.is_action_just_pressed("forward"):
		sprite_2d.animation = "forward"
	if Input.is_action_just_released("forward"):
		sprite_2d.animation = "idle"
	
		
	if Input.is_action_just_released("up"):
		velocity.y += 2
		#Gravity	
		
	if Input.is_action_pressed("ui_down",true):
		sprite_2d.play("face_down")
		
	if Input.is_action_pressed("ui_left",true):
		sprite_2d.play("left")
	
	if Input.is_action_pressed("ui_right",true):
		sprite_2d.play("right")
		
			
func shoot():
	var b = preload ("res://bullet.tscn").instantiate()
	get_tree().root.add_child(b)
	b.transform = $Muzzle.global_transform
	
func shoot2():
	var c = preload ("res://bullet2.tscn").instantiate()
	get_tree().root.add_child(c)
	c.transform = $Muzzle.global_transform
	
	var isLeft = velocity.x < 0
	sprite_2d.flip_h = isLeft

func player_hit():
	health -= 1
	if health ==0:
		queue_free()

Script for Enemy

extends CharacterBody2D

var b = preload ("res://bullet.tscn")
var c = preload ("res://bullet2.tscn")

var Bullet = preload("res://mob_bullet.tscn")

@export var bullet2 : PackedScene

var speed = 50
@export var health = 10

var player = null
var canshoot = true

@onready var bowShoot =$bowShoot

@onready var Spawnpos =$Spawnpos
	
func _ready():
	velocity = transform.x * speed
	
func _physics_process(delta):
	
	var collision = move_and_collide(velocity * delta)
	if collision:
		velocity = velocity.bounce(collision.get_normal())
		
func _on_Shootspeed_timeout():
	canshoot = true
	$Shootspeed.start()
	canshoot = false
		
func enemy_hit():
	health -= 1
	if health == 0:
		queue_free()
		
func get_input():
	
	var dir = Input.get_axis("back", "forward")
	velocity = transform.x * dir * speed
	
	move_and_slide()
	
func _on_detection_body_entered(body: Node2D) -> void:
	if body.is_in_group("mob"):
		player = body
		
	var movement =Vector2(-2 , 0)
	
	if player:
		movement = position.direction_to(player.position) * speed
	movement = move_and_collide(movement)

func shoot():
	if canshoot:
		var Bullet = Bullet.instantiate()
		Bullet.position = Spawnpos.global_position
		get_parent().add_child(Bullet)
		
		$ShootSpeed.start()
		canshoot = false  

Script for enemy bullet

extends Area2D


var speed = 400

func _physics_process(delta):
	position.x -= delta * speed


func _on_body_entered(body: Node2D) -> void:
	if body.has_method("playr_hit"):
		body.player_hit()
		queue_free()

you have a typo in your enemy-bullet-script:

has to be “player_hit”

1 Like

Lol, how I missed that

But still, after typing, player_hit the bullet of the enemy, not colliding / hitting the player. The bullets just pass

And they play only once when starting the game

I found the solution for one problem from this pic
Now the player dies when hit by a bullet from enemy

But one problem left, the enemy fire only one time when starting the game

probably because of this:

you immediatly set it to “false” better would be to remove the statement:

func _on_Shootspeed_timeout():
	canshoot = true
	$Shootspeed.start()
1 Like

thanks!
but now the enemy shoot none stop at me and right away when I run the game
I want the enemy to shoot at me only when I am close to his place and if I am far from him, I want him to stop shooting!

I did the detection thing but it’s not working right now maybe something wrong

What about the detection with area2d doesnt work?

should I put it this way in the area2d script alone or for the enemy + enemy_bullet and player script too ?

maybe something missing idk

 func _on_detection_body_entered(body: Node2D) -> void:
	if body.is_in_group("mob"):
		player = body
		
	var movement =Vector2(-2 , 0)
	
	if player:
		movement = position.direction_to(player.position) * speed
	movement = move_and_collide(movement)

what exactly should I put here

no i’d suggest something like the following for the enemy:

func _on_detection_body_entered(body: Node2D) -> void:
	if body.is_in_group("mob"):
		player = body

func _physics_process(delta):
	if player:
		movement = position.direction_to(player.position) * speed
	else:
		movement = velocity * delta
	
	var collision = move_and_collide(movement)
	
	if collision:
		velocity = velocity.bounce(collision.get_normal())

if you want him to stop shooting when you are out of range, you need to connect the body_exited signal to the script and set “player = null” if the body is the player

1 Like

if you want him to stop shooting when you are out of range, you need to connect the body_exited signal to the script and set “player = null” if the body is the player"

I can’t get it to work the enemy keep shooting at all times even if he is far from the player

there must be something I need to do
don’t know what it is!

:frowning:

Did you connect the signal?
i think your timeout-method should look like this.

func _on_Shootspeed_timeout():
	canshoot = true

I dont see where you call the “shoot”-method inside your enemy-script?

Also the bullet should have a lifetime-timer attached to it so it despawns after some time when it doesnt hit anything

1 Like

If you want to apply damage to your player when an enemy bullet touch it, you need to apply every thing from your bullet script this is the object which detect and apply damage + destroy self

2 Likes

Can someone make a fast tutorial on how to make enemy stop shooting at player if he is not close to them or in their area / space ??

I really need to fix this problem to continue with the project

I need to see a step by step
Is there any short video for this on YT

You check for mob not player. (Is your player added to the player group?)

	if body.is_in_group("mob"):
		player = body

I would suggest to say please if you are asking others for a lot of work (that is clearly already on YouTube in many videos).

Most setups with shooting mobs have some sort of detection area. You could also simply check a max shooting range as a quick fix until you get it fully working. It would look something like this.

if (player.global_position - global_position) < shooting_range:
    shoot()

Did you set the player? It said null and i dont see you setting the player anywhere.

var player = null
		

This is in the enemy script