swift 发布于 2023年09月28日
之前和大家分享过一次 Cocos Creator 动画系统的内容, 这篇内容继续上次。 前两周就想把这篇内容写完,但总是各种事情耽误了。这几天总算找出时间把它补上。
这次和大家聊两个事情。
首先,完善一个之前的信息,之前和大家分享过一篇 Cocos Creator 动画系统的文章,里面说到暂时没有发现简便的动画处理方式,看来还是草率了,其实是有的。就是这次要分享的 tween 系统。
然后是之前发现 cocos 的 AnimcationClip 的一个 bug,在 Github 上已经提交给 cocos 团队,并且在新版本中已经修改了。 也算是对 cocos 引擎做了一个小小的贡献,这个bug 存在有一段时间了。
Tween 系统Tween 在 cocos 中文文档中被称作缓动系统。 这也是为什么在查看文档时候没有第一时间发现它的原因。 关于动画,我第一时间想到的是 Animation 这个词而不是 Tween。
我也去查了下, tween 和 animation 在命名上到底是基于什么原因。这是 GPT 给出的解释:
简单的理解就是 tween 是相对简单的动画,比如实现位移,尺寸变化,颜色变化等。 animation 是更加复杂的动画,我们可以自己定义每个关键帧,甚至每一帧都是用完全不同的图片,而不是简单的属性变化。
不过我们大多数时候,其实用不到 Animation 这些复杂的功能。 经常我们只需要一个简单的动画, 那么 tween 才是最适合的选择。
比如我们实现一个位移动画:
// 我们要进行动画的 Node 定义
let nodeToAnimation = ...
// 动画位移的位置
let position1 = new Vec3(100, 100, 0);
let position2 = new Vec3(200,200,0);
//...
// tween动画接口
tween(nodeToAnimation)
.to(1.0, {"position": startPosition}, {easing: "quadIn" })
.delay(1.5)
.to(1.0, {"position": endPosition}, {
easing: "quadOut",
onComplete(target) {
// 动画完成后的操作
},
})
.start();
这个 API 就比我们之前分享的 AnimationClip 简单的多了。
首先 tween(nodeToAnimation)
指定了我们要进行动画的 Node.
然后 .to(1.0, {"position": startPosition}, {easing: "quadIn" })
, 表示我们要在 1.0 秒的时间, 将这个 Node 从当前位置改变到 startPosition 所指定的位置,并且还提供了一个 easing 方法,用来制定动画的加速模式。
接下来,调用 .delay(1.5)
, 表示,第一个动画完成后,等待 1.5秒。 然后进行下一个 .to(1.0, {"position": endPosition})
方法的调用,这次我们还传入了一个 onComplete 的 callback, 这个用于在动画结束后执行一些操作。
简单这几行代码,一个动画过程就实现完成了,这个才是我们更加常用的 API。
有一点要特别提示, 最后的 .start()
方法不要忘了。 否则这个动画不会播放。
关于 tween 更详细的内容, 大家可以去看一下 cocos 的文档: https://docs.cocos.com/creator/manual/zh/tween/tween-interface.html
AnimationClip 的 bug另外一个事情就是之前提到的 AnimationClip 的一个 bug 也提交给 cocos 团队了,关于这个 bug 的详细描述, 可以参考之前一篇内容 http://swiftcafe.io/post/cocos-animation.md
当然,下面的截图其实也已经基本说明问题了,就是一个逻辑判断写反了的问题。 这个在我们日常工作中其实也是一个发生概率不小的事情。 这也是一个写代码习惯的问题。
这个方法之前的逻辑是这样的: if (!ArrayUtils.contains(this._clips, clip)) {
出现问题的版本是这样的: if (js.array.contains(this._clips, clip)) {
。
也就是说,发生问题的根源是这个取反符号 !
反正我自己写代码的时候很少会用取反运算符,我宁可去用 xxx == false 这样看似比较笨的表达式来完成同样的逻辑。 上面这个例子还算比较容易理解的,我们有时候会看到同样一个逻辑,有的开发者会用看似很巧妙的代码来实现,其实这并不是一个好习惯。
正如 AnimationClip 出现的这个 bug,它怎么发生的,我大概率能猜出来,可能是某个版本 contains 这个方法的 API 调用方式变了,要从 ArrayUtils.contains
改成 js.array.contains
。 这就需要所有调用它的下层代码,比如我们所提到的 AnimationClip 都要替换,然后可能是换了个人,又或者还是这个人,但是过了比较长时间自己也不熟悉这段代码了,于是直接就机械性的替换 contains 调用,又由于 ! 这个取反运算符确实不明显,替换的时候确实没看见,逻辑错误就发生了。
然后单元测试恰好又没覆盖到这块逻辑,所以跑测试也没被检测出来,于是这个 bug 就出现了。
我想如果当时这个判断逻辑是用 if(xxx == false) 而不是用取反运算 !, 这个bug出现的概率就会小很多。 反正我的原则来说,代码最重要的是可读性,能让别人,甚至一段时间过后的你自己,以最快的速度理解它。
写在最后我们在使用各种的各种框架,它们自身也难免会出现一些问题。反正就是更多的思考一下,有时候遇到一些错误,并不一定都能通过搜索引擎去找到解决方案,也并不一定是我们使用的问题,如果你用的框架是开源的,一个比较好的方法就是多看看和你问题相关的源代码,往往能找到一些思路。没准也能帮助你所使用的框架更加完善。
这次分享的内容就这么多,每次找一个主题和大家说一些自己对这个主题的理解,尽量避免长篇大论,知道大家的时间都很宝贵。 也不一定对所有人都有帮助,但保证是真实原创的思维过程。也欢迎你在评论区交流。
如果你觉得这篇文章有帮助,还可以关注微信公众号 swift-cafe,会有更多我的原创内容分享给你~
本站文章均为原创内容,如需转载请注明出处,谢谢。
![]() 发现更多精彩 swift-cafe |