一个简单的 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 然后传入 ActionManager。ActionManager 每帧会调用 sequence 的执行接口,而 sequence 的执行接口逻辑上大抵是遍历所有的 Action,执行当前的 Action,如果完成就标记为 isDone,然后切换下一个 Action 重复上述过程,如果未完成就跳出循环。

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

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

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

2赞


建议你使用
image

1赞

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

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


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

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

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

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