一个简单的 tween stop无效?

import { _decorator, Component, Node, Tween, Vec2, Vec3 } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('test2')
export class test2 extends Component {

tween = null

start() {

    let bg = this.node.getChildByName('Sprite')

    this.tween = new Tween(bg).to(1, {position: new Vec3(100, 100, 0)}).call(()=>{
        this.callback()
    }).call(()=>{
        this.callback2()
    }).start()

}

callback() {
    console.log("1")
    this.tween.stop()
}

callback2() {
    console.log("2")
}

update(deltaTime: number) {
    
}
}

为什么stop无效,日志 “2”也打印了,搞不懂,难道是我用错了吗?

大受震撼!

tween一旦调用则本次不会停止,应该是这么理解,所以在tween里面stop后要求立即停止是不行的,他的stop说的是下一次调用tween之前,也就是本次结束后才stop,很多方面的stop估计都是这么样的

哈???

那提供这个stop函数到底用处何在?还不如以前的stopAction了?

不建议你这么干,这就叫典型的回调自杀
你在回调里把调用者杀了,你说你自己还活不活了呢,调用者的相关信息你还敢用么
放到原生上,搞不好有些内存都已经释放了,你再去用,不会崩溃么,你还记得0x000000不能为read么

我这都明确调用stop,这步还不释放内存吗?而且我这只是简单的一个脚本写法,怎么上升到内存层面了?以前的2.x版本node节点runAction, stopAction不都经常这样用都没什么问题,现在是官方直接去掉了runAction以前的函数,替代方案tween实现起来反而不可以了,你让2.x转过来的人怎么玩的转嘛?

从用户的角度肯定是希望可以立刻stop,但是既然不行,那就另想其他办法也可以实现的,比如设置一个标志位来识别是否tween停止了

不是 stop 失效了,是 call 在缓动中的逻辑的原因。

看了下引擎源码,缓动在 start 后封装成一个 sequence 然后传入 ActionManagerActionManager 每帧会调用 sequence 的执行接口,而 sequence 的执行接口逻辑上大抵是遍历所有的 Action,执行当前的 Action,如果完成就标记为 isDone,然后切换下一个 Action 重复上述过程,如果未完成就跳出循环。

因为 call 动作在触发回调后立马被标记为完成,并且切换到下一个动作(在你的逻辑这里就是第二个 call),所以连续的 call 会在同一帧中按顺序触发回调。

stop 调用时是从 ActionManager 中移除封装成 sequenceAction,因此虽然 sequence 确实从 ActionManager 中移除了,但是很不幸连续的 call 动作在同一帧内就触发回调了 :cry:

这个设计对调用者来说确实有点怪,不过从逻辑上来看,连续的 call 或许可以合并成一个然后根据逻辑去判断是否执行后面的 call 的逻辑:thinking:

2赞


建议你使用
image

1赞

去读一遍API的逻辑应该就明白是怎么回事儿了

这个确实可以 立即停止,我也是用这个api


2.4.5也必现这个bug,一个骚操作是这样改下源码能临时解决

我不建议这样修改,既然官方没提供这个方式,那就应该是知道这样做会有什么内存问题的,所以还是用其他api比较稳妥

哦,您的建议我了解了。我这是给提问者提供的一个可选方案哈。

至于官方没提供这个方式的说法,官方可能还不知道有这个bug,内存问题什么的,额,您可能多虑了。