使用DOTween实现拖动UI时的补间动画 仅Y轴跟随手指移动问题排查
问题排查
- 触发时机错误:
GestureState.Up通常对应手势抬起的状态,拖动跟随逻辑应该放在手势移动中的状态回调(如GestureState.Move)下 - 缓动冲突:每次触发都调用带0.5s时长的
DOMove方法,上一次未完成的缓动会和新缓动冲突,导致跟随延迟、错位 - 坐标系不匹配:
_MousePos是屏幕像素坐标,不能直接赋值给Transform的位置坐标(UGUI为锚点局部坐标,2D Sprite为世界坐标),直接赋值会出现大幅位置偏差 - X轴赋值错误:代码写死目标X坐标为0,没有保留图片原本的X轴坐标,不符合X轴固定的需求
修正代码
适用UGUI图片场景(绝大多数拖动图片需求为此场景)
public void CallEvent() { // 替换为你手势SDK对应的移动中状态枚举值 case GestureState.Move: if(this.gameObject.name == "Cover") { RectTransform rect = GetComponent<RectTransform>(); RectTransform parentRect = transform.parent.GetComponent<RectTransform>(); // 屏幕坐标转父容器局部坐标,Canvas为Screen Space-Overlay模式时相机传null if (RectTransformUtility.ScreenPointToLocalPointInRectangle(parentRect, _MousePos, null, out Vector2 localPos)) { // 直接赋值坐标实现无延迟跟随,保留原X轴 rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, localPos.y); // 若需使用DOTween实现小幅缓动效果,用以下代码替换上面的直接赋值即可 // rect.DOKill(); // rect.DOAnchorPosY(localPos.y, 0.05f); } } break; }
适用世界空间2D Sprite场景
public void CallEvent() { case GestureState.Move: if(this.gameObject.name == "Cover") { Vector3 worldPos = Camera.main.ScreenToWorldPoint(_MousePos); transform.position = new Vector3(transform.position.x, worldPos.y, transform.position.z); } break; }
注意事项
- 若你的Canvas为Screen Space-Camera模式,
RectTransformUtility.ScreenPointToLocalPointInRectangle的第三个参数需要传入Canvas绑定的渲染相机,不能传null - 若使用DOTween缓动,必须在每次调用缓动前调用
DOKill()杀掉未完成的旧缓动,避免缓动堆积导致错位
内容的提问来源于stack exchange,提问作者heinzQ
相关产品推荐
相关产品推荐

