RayCast problem with animatedsprite3D

Godot Version

4.2.1

Question

Hey boys, I have a problem with the code, namely I would like one raycast to be fired for a shoot animation. So one shoot, one raycast. At the moment, the raycast only fires once and the shoot animation is in a loop.

DebugLogs:

Enemy fired Level:<CSGCombiner3D#37933286770>
— Debugging process stopped —

extends CharacterBody3D
class_name Enemy

const SPEED = 3

var dead = false
var is_attacking = false #new variable

@export var max_hitpoints:= 10
@export var attack_range := 10
@export var attack_damage := 10

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
@onready var navigation_agent_3d = $NavigationAgent3D
@onready var animation_enemy = $AnimatedSprite3D


var player
var provoked := false
var aggro_range := 25
var hitpoints: int = max_hitpoints:
	set(value):
		hitpoints = value
		if hitpoints <= 0:
			die()
		provoked = true

func _ready() -> void:
	player = get_tree().get_first_node_in_group("player")

func _process(_delta: float) -> void:
	if provoked:
		navigation_agent_3d.target_position = player.global_position


func _physics_process(_delta: float) -> void:
	var _next_postion = navigation_agent_3d.get_next_path_position()
	if dead or is_attacking:
		return

	if player == null:
		return
		
	var dir = player.global_position - global_position
	dir.y = 0.0
	dir = dir.normalized()
	
	velocity = dir * SPEED

	
	if not is_on_floor():
		velocity.y -= gravity * _delta

	var direction = global_position.direction_to(_next_postion)
	var distance = global_position.distance_to(player.global_position)

	if distance <= aggro_range:
		provoked = true
		
	if provoked:
		if distance <= attack_range:
			is_attacking = true
			animation_enemy.play("shoot")
		else:
			is_attacking = false
			animation_enemy.play("run")

	if direction:
		look_at_target(direction)
		velocity.x = direction.x * SPEED
		velocity.z = direction.z * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.z = move_toward(velocity.z, 0, SPEED)

	look_at(player.global_position)
	move_and_slide()
	
	attack()
func look_at_target(direction: Vector3) -> void:
	var adjusted_direction = direction
	adjusted_direction.y = 0
	look_at(global_position + adjusted_direction, Vector3.UP, true)
	
func attack() -> void:
	var dist_to_player = global_position.distance_to(player.global_position)
	if dist_to_player > attack_range:
		return
	
	var dir = player.global_position - global_position
	dir.y = 0.0
	dir = dir.normalized()
	rotation.y = atan2(dir.x, dir.z)
	
	var collider = $RayCast3D.get_collider()
	printt("Enemy fired", collider)
	if collider is Player:
		collider.hitpoints -= attack_damage
	#await $AnimatedSprite3D.animation_finished

	
	
func die():
	if dead:
		return
	
	dead = true
	$AnimatedSprite3D.play("die")
	$CollisionShape3D.disabled = true
	await $AnimatedSprite3D.animation_finished

Second version of script

extends CharacterBody3D
class_name Enemy

const SPEED = 3

var dead = false
var is_attacking = false #new variable


@export var max_hitpoints:= 10
@export var attack_range := 10
@export var attack_damage := 10

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
@onready var navigation_agent_3d = $NavigationAgent3D
@onready var animation_enemy = $AnimatedSprite3D


var player
var provoked := false
var aggro_range := 25
var hitpoints: int = max_hitpoints:
	set(value):
		hitpoints = value
		if hitpoints <= 0:
			die()
		provoked = true

func _ready() -> void:
	player = get_tree().get_first_node_in_group("player")

	
func _process(_delta: float) -> void:
	if provoked:
		navigation_agent_3d.target_position = player.global_position


func _physics_process(_delta: float) -> void:
	var _next_postion = navigation_agent_3d.get_next_path_position()
	if dead or is_attacking:
		return

	if player == null:
		return
		
	var dir = player.global_position - global_position
	dir.y = 0.0
	dir = dir.normalized()
	
	velocity = dir * SPEED

	
	if not is_on_floor():
		velocity.y -= gravity * _delta

	var direction = global_position.direction_to(_next_postion)
	var distance = global_position.distance_to(player.global_position)

	if distance <= aggro_range:
		provoked = true
		
	if provoked:
		if distance <= attack_range:
			animation_enemy.play("shoot")
		else:
			animation_enemy.play("run")

	if direction:
		look_at_target(direction)
		velocity.x = direction.x * SPEED
		velocity.z = direction.z * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.z = move_toward(velocity.z, 0, SPEED)

	look_at(player.global_position)
	move_and_slide()
	attack()

func look_at_target(direction: Vector3) -> void:
	var adjusted_direction = direction
	adjusted_direction.y = 0
	look_at(global_position + adjusted_direction, Vector3.UP, true)
	
func attack() -> void:
	var dist_to_player = global_position.distance_to(player.global_position)
	if dist_to_player > attack_range:
		return
	
	var dir = player.global_position - global_position
	dir.y = 0.0
	dir = dir.normalized()
	rotation.y = atan2(dir.x, dir.z)
	
	var collider = $RayCast3D.get_collider()
	printt("Enemy fired", collider)
	if collider is Player:
		collider.hitpoints -= attack_damage
	await $AnimatedSprite3D.animation_finished

	
	
func die():
	if dead:
		return
	
	dead = true
	$AnimatedSprite3D.play("die")
	$CollisionShape3D.disabled = true
	await $AnimatedSprite3D.animation_finished```

I finded a solution:

extends CharacterBody3D
class_name Enemy

const SPEED = 3

var dead = false
var is_attacking = false
var is_moving = false

@export var max_hitpoints := 10
@export var attack_range := 10
@export var attack_damage := 10
@export var fire_rate_enemy := 0.7

var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
@onready var navigation_agent_3d = $NavigationAgent3D
@onready var animation_enemy = $AnimatedSprite3D
@onready var cool_down_attack = $CoolDownAttack

var last_attack_time: float = 0
var attack_cooldown: float = 1.0 / fire_rate_enemy
var time_since_last_attack: float = 0

var player
var provoked := false
var aggro_range := 25
var hitpoints: int = max_hitpoints:
	set(value):
		hitpoints = value
		if hitpoints <= 0:
			die()
		provoked = true

func _ready() -> void:
	player = get_tree().get_first_node_in_group("player")

	
func _process(_delta: float) -> void:
	if provoked:
		navigation_agent_3d.target_position = player.global_position
	time_since_last_attack += _delta


func _physics_process(_delta: float) -> void:
	if dead:
		return

	var _next_position = navigation_agent_3d.get_next_path_position()

	if player == null:
		return
		
	var dir = player.global_position - global_position
	dir.y = 0.0
	dir = dir.normalized()
	
	velocity = dir * SPEED

	var direction = global_position.direction_to(_next_position)
	var distance = global_position.distance_to(player.global_position)

	if distance <= aggro_range:
		provoked = true
		
	if provoked:
		if distance <= attack_range:
			animation_enemy.play("shoot")
			is_attacking = true
			is_moving = false  # Zatrzymaj przeciwnika podczas ataku
		else:
			animation_enemy.play("run")
			is_attacking = false
			is_moving = true

	if is_moving and not is_attacking:
		if direction:
			look_at_target(direction)
			velocity.x = direction.x * SPEED
			velocity.z = direction.z * SPEED
		else:
			velocity.x = move_toward(velocity.x, 0, SPEED)
			velocity.z = move_toward(velocity.z, 0, SPEED)

	look_at(player.global_position)
	if is_attacking:
		attack()
		velocity = Vector3.ZERO
	move_and_slide()


func look_at_target(direction: Vector3) -> void:
	var adjusted_direction = direction
	adjusted_direction.y = 0
	look_at(global_position + adjusted_direction, Vector3.UP, true)
	
func attack() -> void:
	var dist_to_player = global_position.distance_to(player.global_position)
	if dist_to_player > attack_range:
		return
	
	var dir = player.global_position - global_position
	dir.y = 0.0
	dir = dir.normalized()
	rotation.y = atan2(dir.x, dir.z)

	if time_since_last_attack < attack_cooldown:
		return
	
	time_since_last_attack = 0
	
	cool_down_attack.start(1.0 / fire_rate_enemy)
	var collider = $RayCast3D.get_collider()
	print("Enemy fired", collider)
	if collider is Player:
		collider.hitpoints -= attack_damage

	is_attacking = false

	
	
func die():
	if dead:
		return
	
	dead = true
	$AnimatedSprite3D.play("die")
	$CollisionShape3D.disabled = true

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.