Reputation: 3
When I attack with the character, the attack animation happens but when it ends he stays frozen. The character literally doesn't go back to idle, and when pressed to walk nothing happens—he stays still.
Here's my character script:
const SPEED = 5.0
const JUMP_VELOCITY = 4.5
var is_attacking = false
@onready var animemation_tree: AnimationTree =$animation_tree
var smooth_animation := Vector2()
func set_attacking_false():
is_attacking = false
func _physics_process(delta: float) -> void:
# Add the gravity.
if not is_on_floor():
velocity += get_gravity() * delta
$animation_tree.set("parameters/in_air/transition_request", "true")
# Handle jump.
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
if Input.is_action_just_pressed("mouse_left") and is_on_floor():
is_attacking = true
$animation_tree.set("parameters/movements /transition_request", "attack")
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var horizontal_rotation = $camera/horizontal.global_transform.basis.get_euler().y
var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized().rotated(Vector3.UP, horizontal_rotation)
if direction and !is_attacking:
velocity.x = direction.x * SPEED
velocity.z = direction.z * SPEED
$mesh.rotation.y =lerp_angle($mesh.rotation.y, atan2(-direction.x, -direction.z), delta * 5)
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
velocity.z = move_toward(velocity.z, 0, SPEED)
if is_on_floor():
$animation_tree.set("parameters/in_air/transition_request", "false")
if !is_attacking:
if (input_dir.x != 0 or input_dir.y != 0):
$animation_tree.set("parameters/movements /transition_request", "walk")
else:
$animation_tree.set("parameters/movements /transition_request", "idle")
smooth_animation =lerp(smooth_animation, input_dir, delta * 10)
animemation_tree.set("parameters/blend_position", smooth_animation.length())
move_and_slide()
Upvotes: 0
Views: 60
Reputation: 325
After attacking for the first time, you never set the value of is_attacking
back to false
, therefore the AnimationNodeTransition in your BlendTree will always display the last frame of the current attack animation.
Possible solutions (choose one):
In your AnimationPlayer, add a Property Track for is_attacking
to your attack animation, and set its value to false
on the last frame. (Similar to #2.)
In your AnimationPlayer, add a Call Method Track to your attack animation, and call set_attacking_false()
on the last frame. (Similar to #1.)
Connect a callback to the AnimationPlayer's animation_finished
signal that runs only at the end of the attack animation:
func _on_animation_finished(anim_name):
if anim_name == &"Attack":
is_attacking = false
is_attacking
. (May potentially increase coupling. Not recommended for your use case:)# Attacking just started
var attack_time = anim_player.get_animation(&"Attack").length
await get_tree().create_timer(attack_time).timeout
is_attacking = false
Upvotes: 1
Reputation: 19
I don't want to be that guy but this is one of those cases where you don't understand the code you've posted.
I advise you to start there first, learn and understand what you posted, because otherwise it doesn't matter if you get the problem fixed, you have no idea why.
As a heads up and going through the logic, after attacking you need to set the "is_attacking" state back to false, because the character is no longer attacking, that doesn't magically happen by itself.
You also need to request the animation tree to go back to idle to play the correct animation
Upvotes: -1