0 votes

Hi,
I am attempting to write a movement system in 2D for an isometric game using animation_tree.

The problem I am encountering is the player can move during the attack animation, whereas I would like the player to stay still.

I know I need to await (yield) until the animation is finished, however, if I use await $AnimationPlayer.animation_finished it yields forever.

What should I be using instead?

extends CharacterBody2D

@onready var animation_tree = get_node("AnimationTree")
@onready var animation_mode = animation_tree.get("parameters/playback")

var max_speed = 400
var speed = 0
var acceleration = 1200
var move_direction = Vector2(0,0)

var moving = false
var attacking = false

# Called when the node enters the scene tree for the first time.
func _ready():
    pass # Replace with function body.

func _physics_process(delta):
    MovementLoop(delta)

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
    pass

func _unhandled_input(event):
    if event.is_action_pressed('CLICK'):
        moving = false
        attacking = true
        print(position.direction_to(get_global_mouse_position()))
        animation_tree.set('parameters/Melee/blend_position', position.direction_to(get_global_mouse_position()).normalized())
        animation_tree.set('parameters/Idle/blend_position', position.direction_to(get_global_mouse_position()).normalized())
        Attack()

func MovementLoop(delta):
    if attacking == true:
        return

    move_direction.x = int(Input.is_action_pressed("WALK_RIGHT")) - int(Input.is_action_pressed("WALK_LEFT"))
    move_direction.y = (int(Input.is_action_pressed("WALK_DOWN")) - int(Input.is_action_pressed("WALK_UP"))) / float(2)

    if move_direction == Vector2(0,0):
        animation_mode.travel("Idle")
        speed = 0
    else:
        speed += acceleration * delta
        if speed > max_speed:
            speed = max_speed
        var movement = move_direction.normalized() * speed
        velocity = movement
        animation_tree.set('parameters/Walk/blend_position', movement.normalized())

        animation_tree.set('parameters/Idle/blend_position', movement.normalized())
        animation_mode.travel("Walk")
        move_and_slide()

func Attack():
        animation_mode.travel("Melee")
        #await here
        attacking = false
Godot version 4.0
in Engine by (12 points)

I also encountered this problem in Godot 3.4. I am very disapointed to see that it is still there in newer version. AnimationTree does not have its own "animationfinished" signal, and it prevents AnimationPlayer from signalling.

I really hope someone comes up and says it is fixed. Until then, this is how I assesed this situation :
I had to get the animation lenght from AnimationPlayer and yield(get_tree().create_timer(animationlenght),"timeout")
So You can do this with new wait() function. In older version this was not a best sollution, because pause didn't work with dynamic timers and pausing project let players cheat and hasten stagger effects :)

Do you know if pause works with dynamic timers in 4.0?

no, I won't update until I finish my current project. But You can easily test it. Create one sprite, await (yield) 10 seconds, create another sprite. Run this code and try to pause for 10 seconds inbetween sprite creations. If it is broken as in Godot 3, second sprite will be created immadietely after unpausing, otherwise it should hold another 10 seconds.

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.