运行环境:Unity 2018.4.0f1、DOTween v1.2.280、DOTweenPro v1.0.155
原因:
UGUI上的元素,都采用 RectTransform 组件进行变换。在Inspector上显示的坐标都是 anchoredPosition,而非 localPosition。anchoredPosition 和 localPosition 不是任何时候都相等的,不能直接以此数值做 DOLocalMove 动画。
需要明确:
anchoredPosition 为: “子物体pivot” 相对于 “子物体锚点” 的位移。
localPosition 为:“子物体pivot” 相对于 “父物体pivot ” 的位移。
即,如果 “子物体锚点” 没有与 “父物体pivot ” 重合,那 localPosition 就与 anchoredPosition 不等,就可能出现问题。
使用实际的 localPosition 做 DOLocalMove 动画,可以 “一定程度上” 解决问题。
查看 localPosition 的方法如下图:
为什么只是“一定程度上” 解决问题?
因为还需要特别注意的 两个问题。
1、经过测试,如果 DOToweenAnimation组件 上的移动方式为 “TO” 时,总能得到正确的结果;而如果移动方式为 “From” 则不行。这应该是Dotween本身的一个Bug,等待后续在新版本中验证是否会修复。
2、设备的分辨率变化 可能使物体的 localPosition 发生变化(“设备分辨率” =》 “锚点四散的物体的大小” =》 “其子物体的 localPosition”),也就是说,就算你的动画在设计分辨率下运行完美,也可能会在与设计分辨率比例不同的机器上运行出错。
避免此问题的办法是:让物体的 localPosition 保持稳定。即,让其父物体的的大小不随意变化(必要的时候可以考虑增加一些中间层级!)。
---------------------------------------------------- NRatel割 ----------------------------------------------------
想要彻底解决问题,需要直接使用 DOAnchorPos() / DOAnchorPos3D() 。
这样,
在使用时可以直接使用 Inspector 上显示的坐标。
还不用考虑设备分辨率变化对动画的影响(物体的 anchoredPosition 不受其父物体大小的影响)。
其实,在UGUI上,对位置的操作(尤其是动画)应尽量针对 anchoredPosition,而非 localPosition。
---------------------------------------------------- NRatel割 ----------------------------------------------------
代码中不用说,主要的问题是 DOTweenAnimation 组件本身并没有 AnchorPos/AnchorPos3D 的可选项。
好在源代码开放且简单,可以自行对其进行扩展。
需要增加代码的地方(这里只实现 AnchorPos3D ):
1、(DOTweenAnimation 中),增加动作类型。
2、(DOTweenAnimation 中),最终调用逻辑方法 DOAnchorPos3D。
3、(DOTweenAnimation 中),支持 DoRestart 时重新计算起始位置。
4、(DOTweenAnimationInspector 中),在 _AnimationTypeToComponent 字典中增加一行,用于约束 “动作类型 可作用于的 组件”。
5、(DOTweenAnimationInspector 中),增加动画类型字符串,用于在Inspector上展示,以及与 DOTweenAnimation组件中的 AnimationType 类型对应。
6、(DOTweenAnimationInspector 中),设置默认值。
7、(DOTweenAnimationInspector 中),绘制一个Vector3用于填写坐标 、一个单选用于选择是否Snapping、一个单选用于选择是否 Relative。
---------------------------------------------------- NRatel割 ----------------------------------------------------
结果如下,运行与预期完全一致: