给cc.Animation组件提个小小建议!

使用到了Animation组件的事件监听,不小踩到一个坑,也不算是坑,应该是自己的问题,但更希望creator能做的更智能一点。

写了一个播放动画的函数

playAnimation(callback) {
        ...
	let animation = xxxNode.getComponent(cc.Animation);
        //播放动画 
	animation.play();
        //监听动画完毕
	animation.on('finished', () => {
             //执行回调
             callback(); 
        });
}

不知道你能看出上面代码有什么问题吗?建议你也看看自己有没有类似的代码。

我刚开始也没发现,多看两遍就发现问题了,这个playAnimation函数被执行多次后callback也会被执行了多次,因为
每次animation.on(‘finished’, …)都会注册一个新的回调函数。

按经验有on方法就应该有off方法,非常的高兴我找到问题的解决办法了。

function playAnimation(callback) {
        ...
	let animation = xxxNode.getComponent(cc.Animation);
        //播放动画 
	animation.play();
        //监听动画完毕
	animation.on('finished', () => {
	     //注销finished事件
             animation.off('finished'); 
             //执行回调
             callback();
	})
}

满以为问题解决了,结果没想到还是老样子,只好看看cc.Animation.off的源码

off: function (type, callback, target, useCapture) {
        this._init();
        var listeners = this._listeners;
        var nameToState = this._nameToState;

        for (var i = listeners.length - 1; i >= 0; i--) {
            var listener = listeners[i];
            //原来四个函数都要去检查,我就吃亏在这里了
            if (listener[0] === type &&
                listener[1] === callback &&
                listener[2] === target &&
                listener[3] === useCapture) {

                for (var name in nameToState) {
                    var state = nameToState[name];
                    state.off(type, callback, target, useCapture);
                }

                listeners.splice(i, 1);
            }
        }
    },

我又很高兴找到办法了,可我外面优雅的代码变成下面这样了,感觉有点不爽:

function playAnimation(callback) {
        ...
	let animation = xxxNode.getComponent(cc.Animation);
        //播放动画 
	animation.play();
        //将原来匿名函数改写成有名函数了
        let finished = () => {
             //有名字才能传递第二个参数
             animation.off('finished', finished); 
             callback();
        };
	animation.on('finished', finished);
}

我的问题来了,官方能不能将off函数写的智能一点,可以接受一个参数,二个参数,三个参数等等,相当于函数重载,不同参数个数,功能不一样。 而且没有一个offAll的功能,我特别喜欢用匿名函数,需要一个一个的移除,不仅费时,还特别难看,还需要关心那里有on,有没有对应的off,感觉像回到写c++了。

1赞

如果你用的是 1.6,我记得 off 是支持只传一个参数的。

只传一个 ‘finished’,就相当于 offAll 了。

1赞

另外,1.5 里面,你优雅的匿名方法,也是可以 off 的,只要

	var finished = animation.on('finished', () => {
	     //注销finished事件
             animation.off('finished', finished); 
             //执行回调
             callback();
	})

或者

	animation.once('finished', callback)
1赞

我在Animation类中没有搜索once方法,运行时是有的,没想到是继承了EventTarge。
非常感谢你的帮助!

‘被执行多次后callback也会被执行了多次’ 我也被这个坑