--- title: Defold 中的属性动画 brief: 本手册描述了如何在 Defold 中使用属性动画。 --- # 属性动画 所有数值属性(数字、vector3、vector4 和四元数)以及着色器常量都可以使用内置动画系统进行动画制作,使用函数 `go.animate()`。引擎将根据给定的播放模式和缓动函数自动为您对属性进行"tween"处理。您还可以指定自定义缓动函数。 ![Property animation](images/animation/property_animation.png) ![Bounce loop](images/animation/bounce.gif) ## 属性动画 要为游戏对象或组件属性制作动画,请使用函数 `go.animate()`。对于 GUI 节点属性,相应的函数是 `gui.animate()`。 ```lua -- 将位置属性的 y 组件设置为 200 go.set(".", "position.y", 200) -- 然后为其制作动画 go.animate(".", "position.y", go.PLAYBACK_LOOP_PINGPONG, 100, go.EASING_OUTBOUNCE, 2) ``` 要停止给定属性的所有动画,请调用 `go.cancel_animations()`,或者对于 GUI 节点,调用 `gui.cancel_animation()`: ```lua -- 停止当前游戏对象上的欧拉 z 旋转动画 go.cancel_animations(".", "euler.z") ``` 如果您取消复合属性(如 `position`)的动画,则任何子组件(`position.x`、`position.y` 和 `position.z`)的动画也将被取消。 [属性手册](/manuals/properties) 包含了游戏对象、组件和 GUI 节点上所有可用的属性。 ## GUI 节点属性动画 几乎所有 GUI 节点属性都可以制作动画。例如,您可以通过将节点的 `color` 属性设置为完全透明来使其不可见,然后通过将颜色动画为白色(即无色调颜色)使其淡入视图。 ```lua local node = gui.get_node("button") local color = gui.get_color(node) -- 将颜色动画为白色 gui.animate(node, gui.PROP_COLOR, vmath.vector4(1, 1, 1, 1), gui.EASING_INOUTQUAD, 0.5) -- 将轮廓红色组件动画化 gui.animate(node, "outline.x", 1, gui.EASING_INOUTQUAD, 0.5) -- 并移动到 x 位置 100 gui.animate(node, hash("position.x"), 100, gui.EASING_INOUTQUAD, 0.5) ``` ## 完成回调 属性动画函数 `go.animate()` 和 `gui.animate()` 支持一个可选的 Lua 回调函数作为最后一个参数。当动画播放到结束时将调用此函数。对于循环动画,或者当动画通过 `go.cancel_animations()` 或 `gui.cancel_animation()` 手动取消时,永远不会调用该函数。回调可用于在动画完成时触发事件或将多个动画链接在一起。 ## 缓动 缓动定义了动画值如何随时间变化。下面的图像描述了随时间应用的函数以创建缓动效果。 以下是 `go.animate()` 的有效缓动值: |---|---| | `go.EASING_LINEAR` | | | `go.EASING_INBACK` | `go.EASING_OUTBACK` | | `go.EASING_INOUTBACK` | `go.EASING_OUTINBACK` | | `go.EASING_INBOUNCE` | `go.EASING_OUTBOUNCE` | | `go.EASING_INOUTBOUNCE` | `go.EASING_OUTINBOUNCE` | | `go.EASING_INELASTIC` | `go.EASING_OUTELASTIC` | | `go.EASING_INOUTELASTIC` | `go.EASING_OUTINELASTIC` | | `go.EASING_INSINE` | `go.EASING_OUTSINE` | | `go.EASING_INOUTSINE` | `go.EASING_OUTINSINE` | | `go.EASING_INEXPO` | `go.EASING_OUTEXPO` | | `go.EASING_INOUTEXPO` | `go.EASING_OUTINEXPO` | | `go.EASING_INCIRC` | `go.EASING_OUTCIRC` | | `go.EASING_INOUTCIRC` | `go.EASING_OUTINCIRC` | | `go.EASING_INQUAD` | `go.EASING_OUTQUAD` | | `go.EASING_INOUTQUAD` | `go.EASING_OUTINQUAD` | | `go.EASING_INCUBIC` | `go.EASING_OUTCUBIC` | | `go.EASING_INOUTCUBIC` | `go.EASING_OUTINCUBIC` | | `go.EASING_INQUART` | `go.EASING_OUTQUART` | | `go.EASING_INOUTQUART` | `go.EASING_OUTINQUART` | | `go.EASING_INQUINT` | `go.EASING_OUTQUINT` | | `go.EASING_INOUTQUINT` | `go.EASING_OUTINQUINT` | 以下是 `gui.animate()` 的有效缓动值: |---|---| | `gui.EASING_LINEAR` | | | `gui.EASING_INBACK` | `gui.EASING_OUTBACK` | | `gui.EASING_INOUTBACK` | `gui.EASING_OUTINBACK` | | `gui.EASING_INBOUNCE` | `gui.EASING_OUTBOUNCE` | | `gui.EASING_INOUTBOUNCE` | `gui.EASING_OUTINBOUNCE` | | `gui.EASING_INELASTIC` | `gui.EASING_OUTELASTIC` | | `gui.EASING_INOUTELASTIC` | `gui.EASING_OUTINELASTIC` | | `gui.EASING_INSINE` | `gui.EASING_OUTSINE` | | `gui.EASING_INOUTSINE` | `gui.EASING_OUTINSINE` | | `gui.EASING_INEXPO` | `gui.EASING_OUTEXPO` | | `gui.EASING_INOUTEXPO` | `gui.EASING_OUTINEXPO` | | `gui.EASING_INCIRC` | `gui.EASING_OUTCIRC` | | `gui.EASING_INOUTCIRC` | `gui.EASING_OUTINCIRC` | | `gui.EASING_INQUAD` | `gui.EASING_OUTQUAD` | | `gui.EASING_INOUTQUAD` | `gui.EASING_OUTINQUAD` | | `gui.EASING_INCUBIC` | `gui.EASING_OUTCUBIC` | | `gui.EASING_INOUTCUBIC` | `gui.EASING_OUTINCUBIC` | | `gui.EASING_INQUART` | `gui.EASING_OUTQUART` | | `gui.EASING_INOUTQUART` | `gui.EASING_OUTINQUART` | | `gui.EASING_INQUINT` | `gui.EASING_OUTQUINT` | | `gui.EASING_INOUTQUINT` | `gui.EASING_OUTINQUINT` | ![Linear interpolation](images/properties/easing_linear.png) ![In back](images/properties/easing_inback.png) ![Out back](images/properties/easing_outback.png) ![In-out back](images/properties/easing_inoutback.png) ![Out-in back](images/properties/easing_outinback.png) ![In bounce](images/properties/easing_inbounce.png) ![Out bounce](images/properties/easing_outbounce.png) ![In-out bounce](images/properties/easing_inoutbounce.png) ![Out-in bounce](images/properties/easing_outinbounce.png) ![In elastic](images/properties/easing_inelastic.png) ![Out elastic](images/properties/easing_outelastic.png) ![In-out elastic](images/properties/easing_inoutelastic.png) ![Out-in elastic](images/properties/easing_outinelastic.png) ![In sine](images/properties/easing_insine.png) ![Out sine](images/properties/easing_outsine.png) ![In-out sine](images/properties/easing_inoutsine.png) ![Out-in sine](images/properties/easing_outinsine.png) ![In exponential](images/properties/easing_inexpo.png) ![Out exponential](images/properties/easing_outexpo.png) ![In-out exponential](images/properties/easing_inoutexpo.png) ![Out-in exponential](images/properties/easing_outinexpo.png) ![In circlic](images/properties/easing_incirc.png) ![Out circlic](images/properties/easing_outcirc.png) ![In-out circlic](images/properties/easing_inoutcirc.png) ![Out-in circlic](images/properties/easing_outincirc.png) ![In quadratic](images/properties/easing_inquad.png) ![Out quadratic](images/properties/easing_outquad.png) ![In-out quadratic](images/properties/easing_inoutquad.png) ![Out-in quadratic](images/properties/easing_outinquad.png) ![In cubic](images/properties/easing_incubic.png) ![Out cubic](images/properties/easing_outcubic.png) ![In-out cubic](images/properties/easing_inoutcubic.png) ![Out-in cubic](images/properties/easing_outincubic.png) ![In quartic](images/properties/easing_inquart.png) ![Out quartic](images/properties/easing_outquart.png) ![In-out quartic](images/properties/easing_inoutquart.png) ![Out-in quartic](images/properties/easing_outinquart.png) ![In quintic](images/properties/easing_inquint.png) ![Out quintic](images/properties/easing_outquint.png) ![In-out quintic](images/properties/easing_inoutquint.png) ![Out-in quintic](images/properties/easing_outinquint.png) ## 自定义缓动 您可以通过定义一个包含一组值的 `vector` 来创建自定义缓动曲线,然后提供该向量而不是上述预定义的缓动常量之一。向量值表示从起始值(`0`)到目标值(`1`)的曲线。运行时从向量中采样值,并在计算向量中表达的点之间的值时进行线性插值。 例如,向量: ```lua local values = { 0, 0.4, 0.2, 0.2, 0.5, 1 } local my_easing = vmath.vector(values) ``` 产生以下曲线: ![Custom curve](images/animation/custom_curve.png) 以下示例导致游戏对象的 y 位置根据平方曲线在当前位置和 200 之间跳跃: ```lua local values = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 } local square_easing = vmath.vector(values) go.animate("go", "position.y", go.PLAYBACK_LOOP_PINGPONG, 200, square_easing, 2.0) ``` ![Square curve](images/animation/square_curve.png)