引擎从3.8.3升级到3.8.6后,tween缓动细节差异导致bug

  • Creator版本:3.8.3 => 3.8.6

  • 问题描述:
    升级到3.8.6版本后,缓动播放过程中,如果修改对象的active为false,会让缓动暂停,再次修改为active为true,会让缓动继续播放。
    在之前的3.8.3版本是不管对象的active怎么变化,缓动动画都会一直播放下去。
    这个细节变化对项目的影响会很大,目前项目里很多逻辑与动画表现效果都会因为3.8.6的这个新特性导致“出现bug”。

  • 需求:
    想要了解官方对这个事情的定性是什么?属于bug,还是后续方向都是这样设计的。
    如果属于bug的话,后续大概什么时候修改呢?
    如果属于后续方向都是这样设计的,这边项目会安排时间去处理。因为涉及的项目内容范围很多,修改会占用不少时间精力。
    希望官方可以给个明确的方向。这边好做相应的处理。

  • 实例代码:
    在3.8.3中是正常输出结果 A C B
    在3.8.6中的输出结果是 A C
    image

1赞

我也好奇,蹲一个结果。

我刚也是3.8.3升级到3.8.6, 刚也发现这个问题了, 唉! 真不省心,每次升级都给你带来点小意外. 问题不大,但是要改一遍挺恶心的

记得3.8.5tween系统有了一次整体升级。后续应该都是根据这个改吧

我也觉得这种功能的修改起码要在公告里提醒一下吧……

最好有官方文档梳理下每个版本的变更,方便大家查阅

我咋觉得,3.8.6的这种才是正确的

1赞

嗯,不管哪种都是正确的
不过区别在于它之前的版本都是那样处理的,后面突然又换了一种方式
项目的各种缓动都已经按之前的逻辑处理
需要官方给一个明确的方向才行,要不每次这样改动,真顶不住

1赞

这个确实是。不过,这种提示,感觉很难写,因为有些变化可能官方都想不到 :joy:

如果 tween 的 target 是 Node,那么 tween 的 pause、resume、destroy 的状态是需要跟 Node 关联在一起的。Creator 2.x 是这样的行为,我觉得是合理的,否则用户需要自己管理 tween 的各种状态。如果一个 Node 是 active 为 false 的禁用状态,那么它身上的属性还持续被 TweenSystem 更新,是不太符合逻辑的。所以在 v3.8.4 中,我们做了此优化,也为了保持跟 Creator 2.x 的行为一致性。

@vajoy v3.8.4 的 Release Note 中有此说明:

考虑到,还是有部分用户,可能不希望 Tween 关联 Node 的状态,我们计划在 3.8.7 中,添加一个接口,供用户关闭此关联。详见:

@929316378 可以参考上面的 PR 修改,然后为不需要此功能的 Tween 调用 t.bindNodeState(false).
注意,这个接口需要在 start tween 之前调用。

或者,你不想加接口,那么定制引擎,把 action-manager.ts 中的 _registerNodeEvent 相关实现注释掉几颗。

1赞

感谢反馈 :smiley:

就像上面说的,我是感觉不管那种行为都蛮合理。
取决于先接触哪个版本吧 :rofl:
项目会根据 “首次接触” 的特性去做,如果中途切换了效果,哪怕是切换回最原本的效果。对使用中途版本的开发者来说,确实是很头疼的一件事情。

新加一个控制选项去处理,觉得是最合适的方案了 :+1:

嗯,先加了一个控制函数,想来想去,目前名字叫 bindNodeTarget

原来有想一个名字叫 associateWithNodeState 感觉太长,太繁琐了。

大家怎么看?取名需要短、能够准确表达意思。

或者直接叫 bindNode ?

@929316378 这个的确是漏考虑了,因为之前的确是按修 bug 的思路去处理的,3.8.4 之前的逻辑与 2.x 不一致,本身就是有问题的。用户从 2.x 升级上来也会懵。但的确没有考虑到开发者会在 node 禁用状态,还需要更新持续更新其属性的情况。

嗯,能理解开发组的思路,在node禁用状态下,停止缓动可以优化性能等,这对项目来说是很有用的。 :smiley:

这边对 “node的激活状态” 敏感的点在于:“缓动结束后的回调”。
关键的点在于 “某个缓动动画”,而不是 “某个node”。

有点好奇上面说的 “ t.associateNodeState(false) ”
是指像 Tween.stopAllByTarget(node) 一样,直接停止该node对全部缓动的激活状态监听吗?
还是 tween(node).associateNodeState(false).start() 一样,只对该次缓动停止对node的激活状态监听?

如果方便的话,我是更倾向是后者,对该次缓动停止对node的激活状态监听的。

取名的话,感觉可以折中一下,取 bindNodeState ? :rofl:

associateNodeState(false) 表示缓动的 pause 、resume、destroy 不与 node 有任何关联。需要上层手动去控制着 3 个状态,内部不会去监听 node 的状态变化进而控制缓动的状态。

而 associateNodeState(true) (默认)则相反,node active 为 false 的时候,缓动自动暂停,为 true 的时候,缓动自动恢复,node destroy 后,缓动自动停止。

嗯,bindNodeState 感觉更加明确一点。:+1

1赞

PR 已更新。Renamed to bindNodeState.

:grin:好的,谢谢

1赞

:+1: 好的,谢谢