[deleted]
I want to have an attacking state and have it wait for the animation to finish before changing state. The problem is that when i spam the attack bind (left mouse button) it triggers more than once, freezes the animation and it awaits forever for an animation that never finishes. The attack state code is pretty much the same as the dodge state but when i spam the dodge bind (shift) it doesn't do that.
Video demonstration
State Machine Class
Click to reveal Click to hide
extends Node
class_name StateMachine
@export var current_state: State
var states: Dictionary = {}
func _ready() -> void:
for child in get_children():
if child is State:
states[child.name] = child
child.transitioned.connect(on_child_transitioned)
current_state.Enter()
func _process(delta: float) -> void:
current_state.Update(delta)
func _physics_process(delta: float) -> void:
current_state.Physics_update(delta)
func on_child_transitioned(new_state_name: String) -> void:
var new_state = states.get(new_state_name)
if new_state != null:
if new_state != current_state:
current_state.Exit()
new_state.Enter()
current_state = new_state
State Class
Click to reveal Click to hide
extends Node
class_name State
signal transitioned(new_state_name: String)
func Enter() -> void:
pass
func Exit() -> void:
pass
func Update(_delta: float) -> void:
pass
func Physics_update(_delta: float) -> void:
pass
Attack State
Click to reveal Click to hide
extends State
class_name AttackState
@export var actor: CharacterBody3D
@export var forward_movement: float
@onready var animation_player: AnimationPlayer = $"../../AnimationPlayer"
@onready var armature: Node3D = $"../../Armature"
@onready var spring_arm: SpringArm3D = $"../../SpringArm3D"
func Enter() -> void:
animation_player.play("Attack_1")
animation_player.speed_scale = 2.5
actor.velocity = -armature.transform.basis.z * forward_movement
func Physics_update(_delta: float) -> void:
await animation_player.animation_finished
#if not animation_player.is_playing():
var move_direciton = InputManager.get_move_direction_rotated(spring_arm)
if move_direciton:
transitioned.emit("Run")
else:
transitioned.emit("Idle")
Dodge State
Click to reveal Click to hide
extends State
class_name DodgeState
@export var actor: CharacterBody3D
@export var forward_movement: float
@onready var animation_player: AnimationPlayer = $"../../AnimationPlayer"
@onready var spring_arm: SpringArm3D = $"../../SpringArm3D"
@onready var armature: Node3D = $"../../Armature"
func Enter() -> void:
animation_player.play("Dodge")
animation_player.speed_scale = 2.5
actor.velocity = -armature.transform.basis.z * forward_movement
func Physics_update(_delta: float) -> void:
await animation_player.animation_finished
var move_direciton = InputManager.get_move_direction_rotated(spring_arm)
if move_direciton:
transitioned.emit("Run")
else:
transitioned.emit("Idle")
Idle State
Click to reveal Click to hide
extends State
class_name IdleState
@export var actor: CharacterBody3D
@export var speed: float
@onready var animation_player: AnimationPlayer = $"../../AnimationPlayer"
@onready var spring_arm: SpringArm3D = $"../../SpringArm3D"
func Enter() -> void:
animation_player.play("Idle")
animation_player.speed_scale = 0.8
func Physics_update(_delta: float) -> void:
var move_direction = InputManager.get_move_direction_rotated(spring_arm)
if move_direction:
transitioned.emit("Run")
else:
InputManager.stop_actor(actor, speed)
if Input.is_action_just_pressed("attack1"):
transitioned.emit("Attack")
elif Input.is_action_just_pressed("jump"):
transitioned.emit("Jump")
elif Input.is_action_just_pressed("dodge"):
transitioned.emit("Dodge")