for循环动态创建节点,并对节点使用已经初始化的tween动作,只有最后一个节点正确运动

大家好!请教一个奇怪的问题:我在编写一个在start生命周期回调函数中,读取json文件(里面是x y坐标构成的数组,共3对坐标),然后for循环动态生成敌人节点,并给敌人节点添加tween动作的示例代码。奇怪的是,tween动作的初始化如果放在for循环前面,那么只有最后一个节点才会正确运动。

  • Creator 版本: 2.4.12

  • 目标平台: firefox, chrome

  • 首个报错: 浏览器控制台无报错

  • 重现方式:在start生命周期回调函数中,有如下一段代码
    let enemy_list = this.enemies.json;
    let patrol = cc.tween().by(0.2, {y: -100}).by(0.4, {y: 200}).by(0.2, {y: -100});
    for( let i = 0; i < enemy_list.length; i++) {
    //dynamiclly generate enemies
    let enemy_node = cc.instantiate(this.enemyPrefab);
    enemy_node.parent = cc.find(“Canvas/bg”);
    enemy_node.setPosition(enemy_list[i].x, enemy_list[i].y);
    cc.tween(enemy_node).then(patrol).repeatForever().start();
    }

我以为初始化的tween动作 patrol 是公用的,所以放在for循环外部,但这样运行的效果只有最后一个节点运动是正确的,前两个节点只是微微抖动,参见上传的gif动图。QQ录屏20231130155039

如果把初始化 patrol 的语句插到for循环中倒数第二句的位置,则三个节点都运行正常。

但我不理解初始化放在for循环外部为什么运动会出错,不知道是我对tween接口的使用理解有误,还是对js理解有误?

我觉得 patrol 要 clone 一下

cc.tween(enemy_node).then(patrol.clone(enemy_node)).repeatForever().start();

但是又觉得太长了

let patrol = cc.tween().by(0.2, {y: -100}).by(0.4, {y: 200}).by(0.2, {y: -100}).union().repeatForever();
...
patrol. Clone(enemy_node).start();

这样就好了。

其实是你对cc.tween的理解有误,每次声明 cc.tween() 的时候,都是创建一个新的 tween 来储存 _action,_target,_tag ,当你用then去传入的时候,实际上用的都是同一个 tween 的 _action,可能导致该action运动的时候互相传参了

function Tween (target) {
this._actions = [];
this._finalAction = null;
this._target = target;
this._tag = cc.Action.TAG_INVALID;
}
Tween.prototype.then = function (other) {
if (other instanceof cc.Action) {
this._actions.push(other.clone());
}
else {
this._actions.push(other._union());
}
return this;
};
要把cc.tween当作一个整体看待,而不是一个action

收到,看到您的示例代码和3楼的解释,应该是我对tween接口理解有误。谢谢!

收到,看源码,我的代码应该是走this._actions.push(other._union());这个分支,所以互相影响了是吧

是的,你想用这种方式也可以传cc.sequence进去

let patrol = cc.sequence(cc.moveBy(0.2,cc.Vec2(0,-100)),cc.moveBy(0.2,cc.Vec2(0,200)),cc.moveBy(0.2,cc.Vec2(0,-100)));

了解,受教了,谢谢!