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
的更多信息:
我在 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
的更多信息: