GODOT - 完全攻击动画不播放

GODOT - Full Attack Animation Not Playing

我在 Godot Game Engine 制作了这个简单的游戏,并且我在游戏的主角中实现了一些动画。

1。 运行

这是我添加的一个简单的运行动画,它在角色移动时播放

2。空闲

这个动画更像是在角色不动时播放的单个图像

3。攻击

当用户按下鼠标左键时播放此动画。

我在攻击动画方面遇到了问题,当我按下鼠标左键时,我的动画没有播放,而是我得到了动画的第一帧,然后角色又回到了空闲动画。

这是它的样子:

这是我的角色代码:

extends KinematicBody2D

var _inputVec = Vector2.ZERO
var VELOCITY = Vector2.ZERO
var LAST_INPUT = Vector2.ZERO
const MAX_SPEED = 70
const ACCELERATION = 500
const FRICTION = 500

onready var animationPlayer = $AnimationPlayer

func _ready():
    print("game started!")

func _physics_process(delta):
    _inputVec.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
    _inputVec.y = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")
    _inputVec = _inputVec.normalized()
    
    if _inputVec != Vector2.ZERO:
        if _inputVec.x > 0:
            animationPlayer.play("playerRunRight")
        elif _inputVec.y < 0:
            animationPlayer.play("playerRunUp")
        elif _inputVec.y > 0:
            animationPlayer.play("playerRunDown")
        else:
            animationPlayer.play("playerRunLeft")

        VELOCITY = VELOCITY.move_toward(_inputVec * MAX_SPEED, ACCELERATION * delta)
        LAST_INPUT = _inputVec
    else:
        VELOCITY = VELOCITY.move_toward(Vector2.ZERO, FRICTION * delta)

        if Input.is_action_just_pressed("ui_lmb"):
            if LAST_INPUT.x > 0:
                animationPlayer.play("playerAttackRight")
            elif LAST_INPUT.y < 0:
                animationPlayer.play("playerAttackUp")
            elif LAST_INPUT.y > 0:
                animationPlayer.play("playerAttackDown")
            else:
                animationPlayer.play("playerAttackLeft")
        else:
            if LAST_INPUT.x > 0:
                animationPlayer.play("playerIdleRight")
            elif LAST_INPUT.y < 0:
                animationPlayer.play("playerIdleUp")
            elif LAST_INPUT.y > 0:
                animationPlayer.play("playerIdleDown")
            else:
                animationPlayer.play("playerIdleLeft")

    VELOCITY = move_and_slide(VELOCITY)

完整项目可在我的 Github Repo

记住 _physics_process 每(物理)帧运行一次。

所以,你按下鼠标左键的一帧,这行要执行:

                animationPlayer.play("playerAttackRight")

但是下一个(物理)帧,你没有按下鼠标左键,所以这个条件是错误的:

        if Input.is_action_just_pressed("ui_lmb"):

然后这一行开始执行:

                animationPlayer.play("playerIdleRight")

因此,您只能看到 "playerAttackRight" 动画的大约一帧。


您将需要跟踪当前状态(运行、正在攻击、空闲)。规则是你可以立即从运行空闲状态变为空闲状态,但是你只能在攻击动画结束时从攻击状态变为空闲状态。

当然,您可以使用变量来跟踪当前状态。您可以采用输入和变量状态的值来决定新状态。然后分别读取状态变量,决定播放哪个动画。您可能还想在某些动画结束时设置状态变量。

要在动画结束时执行某些操作,您可以使用任一资源来产生:

yield(animationPlayer, "animation_finished")

它会在收到 "animation_finished" 信号后恢复您的代码。

或者,否则您可以连接到 "animation_finished" 信号。

顺便说一句,你也可以排队动画:

animationPlayer.queue("name_of_some_animation")

虽然像您一样使用 AnimationPlayer 是可以的。当它变得复杂时,您应该考虑另一个工具:AnimationTree.

创建一个 AnimationTree 节点,给它你的动画播放器,并将根设置为一个新的 AnimationNodeStateMachine。您可以在那里创建状态机,并配置它们之间的转换是立即进行还是在结束时进行。

然后,从代码中,你可以得到状态机播放对象,像这样:

var state_machine = $AnimationTree.get("parameters/playback")

你可以问它当前状态是什么:

var state:String = state_machine.get_current_node()

您可以将其用作决定您想去哪个州的一部分。然后告诉它你想让它进入不同的状态,像这样:

state_machine.travel("name_of_some_state")

并且使用它会尊重您设置的转换,因此您不必在代码中担心它。


您可以在以下位置找到有关使用 AnimationTree 的更多信息: