Phaser 3中如何实现一个动画结束后立即播放另一个动画?
解决Phaser中启动走路动画后循环播放走路动画的问题
问题根源
你的代码在update函数中,只要左右键按下,就会每帧重复执行this.soma.anims.play('startWalking')和this.soma.anims.chain('walking', true)。这会导致startWalking动画被不断重置,永远无法播放完成,自然触发不了后续的链式动画。
修复方案
我们可以通过状态变量跟踪动画状态+动画完成事件来实现需求,确保startWalking只在需要时播放一次,完成后自动切换到循环的walking动画。
修改后的完整代码
const velocity = 100; export class Game extends Phaser.Scene{ constructor(){ super({key: 'game'}) } init(){ this.isWalking = false; // 跟踪是否处于走路状态 } preload(){ this.load.image('soma', 'img/soma.png') this.load.image('placeholder', 'img/placeholder.png') this.load.spritesheet('walking-anim', 'img/walking-anim.png', {frameWidth: 32, frameHeight: 34}) } create(){ this.soma = this.physics.add.sprite(100, 10, 'soma') this.placeholder = this.physics.add.sprite(100, 150, 'placeholder').setImmovable(); this.placeholder.scaleX = 20 this.physics.add.collider(this.soma, this.placeholder) this.placeholder.body.allowGravity = false this.anims.create({ key: 'startWalking', frames: this.anims.generateFrameNumbers('walking-anim', { start: 19, end: 20}), frameRate: 10, repeat: 0 // 确保只播放一次,默认就是0可以不写,但明确标注更清晰 }) this.anims.create({ key: 'walking', frames: this.anims.generateFrameNumbers('walking-anim', { start: 21, end: 37}), frameRate: 10, repeat: -1 // 设置为-1表示无限循环 }) this.anims.create({ key: 'idle', frames: this.anims.generateFrameNumbers('walking-anim', { start: 1, end: 3}), frameRate: 2.3, yoyo: true }) this.up = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.UP); this.left = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.LEFT); this.right = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.RIGHT); this.physics.world.setBounds(0, 0, 240, 160); this.soma.setCollideWorldBounds(true) // 监听startWalking动画完成事件 this.soma.on('animationcomplete', (anim) => { if (anim.key === 'startWalking') { this.isWalking = true; this.soma.anims.play('walking'); } }); } update(){ this.soma.body.setVelocityX(0); const isMoving = this.left.isDown || this.right.isDown; if (this.left.isDown){ this.soma.body.setVelocityX(-velocity); this.soma.flipX = true; } if (this.right.isDown){ this.soma.body.setVelocityX(velocity); this.soma.flipX = false; } if (isMoving) { // 如果没在走路状态,且当前不是在播放startWalking,就启动启动动画 if (!this.isWalking && this.soma.anims.currentAnim?.key !== 'startWalking') { this.soma.anims.play('startWalking'); } } else { // 松开按键后重置状态,播放 idle 动画 this.isWalking = false; this.soma.anims.play('idle', true); } } }
关键修改点说明
- 添加状态变量
isWalking:用于跟踪角色是否已经进入持续走路状态,避免重复触发启动动画。 - 动画完成事件监听:在
create中给角色绑定animationcomplete事件,当startWalking播放完成后,自动切换到循环的walking动画,并标记走路状态。 - 优化update中的动画逻辑:只有当角色开始移动且未处于走路状态、当前也没在播放启动动画时,才播放
startWalking;松开按键后重置状态,切回idle动画。
另一种简洁方案:正确使用anims.chain
如果你更倾向于用链式动画,只需确保play和chain只被调用一次,而不是每帧重复执行。可以通过判断当前动画是否是目标动画来实现:
// 在update的isMoving分支中替换为: if (!this.soma.anims.isPlaying || this.soma.anims.currentAnim.key === 'idle') { this.soma.anims.play('startWalking'); this.soma.anims.chain('walking'); }
这种方式的核心是避免每帧重复调用play和chain,只在从idle切换到移动时执行一次链式设置。
内容的提问来源于stack exchange,提问作者slvr402
相关产品推荐
相关产品推荐

