3.8 缓动

优质
小牛编辑
126浏览
2023-12-01

为了全面兼容和保持 Cocos Creator 2D 缓动系统的使用体验,在v1.1版本 Cocos Creator 3D 移植了所有的 Cocos Creator 2D 功能实现。

注:action已经被废弃了,请使用tween;

注:在v1.0.3版本开始将不再依赖tween.js,如果使用了tween.js的相关特性,请注意及时适配

注:在v1.0.4版本开始,toby的可选属性中增加了onStart,onUpdate,onComplete回调;

与此前tween.js不同的地方主要是可选属性,为以下内容:

  • easing 的值定义变动了(这里做了兼容性处理)
  • 除了 easingonStartonUpdateonComplete,其它属性暂不支持(这里做了检查,控制台会有相应的警告)

简单示例

import { _decorator, Component, Vec3, tween } from "cc";

@ccclass("tween-test")
export class tweentest extends Component {

    private _pos: Vec3 = new Vec3(0, 0, 0);

    start () {
        /** 缓动 _pos */
        tween(this._pos)
            .to(3, new Vec3(10, 10, 10), { easing: 'bounceInOut' })
            .to(3, new Vec3(0, 0, 0), { easing: 'elasticOut' })
            .union()
            .repeat(2) // 执行 2 次
            .start();

        /** 缓动 Node,这里将缓动 Node 的 position 属性 */
        tween(this.node)
            .to(3, { position: new Vec3(10, 10, 10) }, { easing: 'bounceInOut' })
            .to(3, { position: new Vec3(0, 0, 0) }, { easing: 'elasticOut' })
            .union()
            .repeat(2) // 执行 2 次
            .start();
    }
}

注意事项

repeat 语义

此前repeat的语义为重复几次,为了全面保持 Creator 2D 的设计,所以现在repeat为执行几次,即repeat(1)代表执行一次。

一些限制

为了降低更新Node Transform信息的频率,Node内部维护了一个dirty状态,只有在调用了可能会改变 Node Transform信息的接口,才会将dirty置为需要更新的状态。

但目前的接口存在一定的限制,例如:通过this.node.position获取到的position是一个通用的Vec3

当执行this.node.position.x = 1这段代码的时候,只执行了positiongetter,并没有执行positionsetter。由于dirty并没有更新,便会导致渲染时使用的节点的Transform信息没有更新。

目前,我们也不支持这样的调用,而是鼓励使用setPositionpositionsetter,即以下代码方式:

let _pos = new Vec3(0, 1, 0);
this.node.position = _pos;      // 这里将通过 position 的 setter
this.node.setPosition(_pos);    // 这里将通过接口 setPosition

正确的缓动方式

在新的Tween模块中可以对具有gettersetter的属性进行缓动,例如简单示例中nodeposition属性,这样在缓动的过程中,会进行相应的接口进行设置,从而保证dirty正常更新。

注:切换场景时注意停止相应的缓动

Tween 接口介绍

接口解释
to添加一个对属性进行绝对值计算的间隔动作
by添加一个对属性进行相对值计算的间隔动作
set添加一个直接设置目标属性的瞬时动作
delay添加一个延迟时间的瞬时动作
call添加一个调用回调的瞬时动作
target添加一个直接设置缓动目标的瞬时动作
union将上下文的缓动动作打包成一个
then插入一个 Tween 到缓动队列中
repeat执行几次(此前为重复几次,请及时适配)
repeatForever一直重复执行
sequence添加一个顺序执行的缓动
parallel添加一个同时进行的缓动
start启动缓动
stop停止缓动
clone克隆缓动
show启用节点链上的渲染,缓动目标需要为 Node
hide禁用节点链上的渲染,缓动目标需要为 Node
removeSelf将节点移出场景树,缓动目标需要为 Node

to 和 by 的可选属性

定义如下:

interface ITweenOption {
    easing?: TweenEasing | ((k: number) => number);
    progress?: (start: number, end: number, current: number, ratio: number) => number;
    onStart?: (target: object) => {};
    onUpdate?: (target: object, ratio: number) => {};
    onComplete?: (target: object) => {};
}

与 Creator 2D 不同的是新增了onStartonUpdateonComplete等属性,这些属性是回调函数,调用时会传入缓动的目标。

另外, onUpdate调用时还会多传入一个目前缓动的进行值,范围为(0-1]

回调的使用范例

onUpdate为例,以下代码缓动一个位置,然后在onUpdate中将其设置到多个对象上,这样就像是缓动的合批。

import { Node, tween, Vec3 } from "cc";
const nodeArray: Node[] = []; // 此处替换成你的节点数组
const tweenTagertVec3 = new Vec3();
tween(tweenTagertVec3)
    .by(1, new Vec3(1, 1, 1), {
        'onUpdate': (target: Vec3, ratio: number) => {
            for (let i = 0; i < nodeArray.length; i++)
                nodeArray[i].worldPosition = target;
        }
    });

自动销毁

v1.0.4版本开始,当缓动目标为Node时,将会监听其销毁事件进行缓动的自动销毁,调用target方法也会自动更新监听。

相关测试例test-case-3d更多详细介绍,请参考 Creator 的使用缓动系统