--- order: 4 title: 用户输入控制动画 type: 动画 group: 指南和示例 label: Animation/Examples --- 本示例展示了如何在 Galacean 编辑器中让用户的输入控制动画。通过简单的步骤,你将学习如何结合用户输入来控制动画的切换,让角色根据用户的交互进行相应的动作过渡。 如果你是第一次使用动画编辑器,建议先阅读前面几篇文档: [1.播放模型中的动画](/docs/animation/examples/playAnimation/) [2.动画复用](/docs/animation/examples/reuseAnimation/) [3.动画过渡](/docs/animation/examples/crossFade/) ## 0. 准备工作 1. 在开始之前,我们需要有一个包含多个动画的模型, 并将其拖入到场景中。如果你没有模型,可以在点此下载 [模型](https://mdn.alipayobjects.com/oasis_be/afts/file/A*N99IQYh_g5YAAAAAAAAAAAAADkp5AQ/player.glb)。 2. 我们要有一个已编辑好动画过渡的 `动画控制器` 。请参考:[编辑动画控制器](/docs/animation/examples/crossFade/#3-编辑动画控制器)。 ## 1. 添加动画控制参数 为了能够根据用户输入控制动画,首先需要给 `动画控制器` 加一些参数,根据这些参数来切换 `动画状态` 。 1. 切换到 `Parameters` 面板 2. 点击 `+` 添加一个浮点参数 `speed`,并将默认值设置为 0。 ## 2. 添加过渡条件 之前为大家介绍了如何在 `动画状态机` 中添加 `动画过渡`([详细介绍](/docs/animation/examples/crossFade/)),在之前的示例中,时间超过了 `ExitTime` 就会触发过渡。这里我们需要根据用户输入来触发过渡,所以我们需要添加一个 `过渡条件` 。 1. 在 `动画状态机` 中,选中从 `idle` 到 `walk` 的过渡,点击 `Add Condition` 添加一个 `Condition`。 `Condition` 的默认值刚好符合我们的需求,当 `speed` 大于 0 时,就会从 `idle` 过渡到 `walk`。 2. 同样的,选中从 `walk` 到 `run` 的过渡,添加一个 `Condition`,使其 `speed` 大于 5 时,从 `walk` 过渡到 `run`。 3. 选中 `run` 到 `exit` 的过渡,添加一个 `Condition` ,使其 `speed` 为 0 时,从 `run` 退出动画,重新回到 `idle`。 ### 3. 添加脚本 我们需要一个脚本来接收用户输入,并根据用户输入来修改 `speed` 参数的值,以触发动画状态的切换。 添加脚本有两种方式: 1. 右键点击 **[资产面板](/docs/assets/interface)** 中的空白处,选择 `Create` -> `New Empty Script` 2. 点击添加资产按钮 `+`,选择 `New Empty Script` ### 4. 编辑并绑定脚本 1. 双击脚本,打开脚本编辑器,输入以下代码: ```typescript import { Script, Animator, Keys } from '@galacean/engine'; export default class extends Script { animator: Animator; onStart() { this.animator = this.entity.getComponent(Animator); } onUpdate(deltaTime: number) { const inputManager = this.engine.inputManager; if (inputManager.isKeyHeldDown(Keys.KeyW)) { // 如果用户按下 W + Shift 键,则设置 speed 参数值为 6 if (inputManager.isKeyHeldDown(Keys.ShiftLeft)) { this.animator.setParameterValue('speed', 6); } else { // 如果用户仅按住 W 键,则设置 speed 参数值为 1 this.animator.setParameterValue('speed', 1); } } // 如果用户松开 W 键,则设置 speed 参数值为 0 if (inputManager.isKeyUp(Keys.KeyW)) { this.animator.setParameterValue('speed', 0); } } } ``` 关于脚本的详细说明请参考:[脚本](/docs/script/script) 关于用户输入的详细说明请参考:[交互总览](/docs/input/input) 2. 找到 `Animator` 组件所在的实体,为其添加刚刚创建的脚本。 ### 5. 预览动画 与之前的教程不同,因为本次我们为实体添加了脚本,仅点击预览动画按钮,脚本代码是不会生效的,我们需要点击项目预览(项目预览才会编译脚本文件)按钮来预览动画。 当角色处于 `idle` 状态时,按下 `W` 键,角色会从 `idle` 过渡到 `walk`,按住 `Shift` 键,角色会从 `walk` 过渡到 `run`,松开 `W` 键,角色会从 `run` 退出动画,重新回到 `idle`。 ### 6. 优化动画 我们预览时会发现,如果我们在 `walk` 状态时松开 `W` 键,角色并不会切换到 `idle` 状态,而是继续播放 `walk` 动画。这是因为我们并没有从 `walk` 到 `idle` 的过渡。 而且从 `run` 到 `idle` 也没有过渡效果。因为我们是通过重新进入 `entry` 切换到 `idle` 的,而 `entry` 到 `idle` 的过渡的 `Duration` 是 0。想要从 `run` 过渡到 `idle` ,我们可以将 `run` 连接到 `idle`。 同理想要从 `run` 过渡到 `walk` 也需要添加过渡。 再次预览,我们发现 `walk` 到 `idle` 和 `run` 到 `walk` 的过渡效果已经生效了。 但是从 `run` 到 `idle` 的过渡效果并没有生效,而是先到 `walk` 再由 `walk` 到 `idle`,这是因为当 `speed` 参数为 0 时,`run` 到 `walk ` 和 `run` 到 `idle` 的 `Condition` 都满足。 为了避免这种情况,我们可以给 `run` 到 `walk` 再添加一个 `Condition` 并将其设置为 `speed` 大于 0。 这样当我们同时松开 `W` 键和 `Shift` 键时,角色就会从 `run` 直接过渡到 `idle` 了。