You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中Standalone Input Module的ProcessDrag模拟拖拽未按预期运行求助

Unity StandaloneInputModule 模拟触屏拖拽失效解决方案

现有代码核心问题

  • beginDragHandler 每帧重复触发,该事件仅允许在拖拽启动时执行一次,重复调用会打断UGUI内部的拖拽状态
  • 缺少拖拽前置的按下触发步骤,pointerDrag 目标是在按下检测阶段由UGUI射线检测确定的,未提前执行按下操作会导致data.pointerDrag为空,后续拖拽事件无响应目标
  • 每帧生成新的PointerEventData实例,丢失了拖拽上下文的关联信息(比如pointerId、按下起始位置等),UGUI无法识别为同一次拖拽操作
  • 缺少拖拽结束后的抬起、endDrag触发步骤,会导致UI控件的拖拽状态残留

修正后代码实现

1. 调整PointerEventData生成逻辑,移除冗余的beginDrag调用

PointerEventData GeneratePointerData(Vector2 pos, int pointerId = 0)
{
    // 固定fingerId保证同一次拖拽的上下文一致,移动端单指触摸默认id为0
    var touch = new Touch()
    {
        position = pos,
        fingerId = pointerId,
        phase = TouchPhase.Moved
    };
    return GetTouchPointerEventData(touch, out _, out _);
}

2. 重写拖拽模拟逻辑,补全完整操作流程

IEnumerator SimulateDrag(Vector2 from, Vector2 to, float dur)
{
    Input.simulateMouseWithTouches = true;
    // 第一步:触发按下操作,UGUI会在此阶段通过射线检测确定拖拽目标
    var pointerData = GeneratePointerData(from);
    ProcessTouchPress(pointerData, pressed: true, released: false);
    
    // 第二步:仅执行一次拖拽开始事件
    ExecuteEvents.Execute(pointerData.pointerDrag, pointerData, ExecuteEvents.beginDragHandler);
    pointerData.dragging = true;

    float startTime = Time.time;
    float endTime = startTime + dur;
    while (Time.time < endTime)
    {
        float t = Mathf.InverseLerp(startTime, endTime, Time.time);
        Vector2 currentPos = Vector2.Lerp(from, to, t);
        // 复用同一个PointerEventData实例,仅更新位置和位移差
        pointerData.delta = currentPos - pointerData.position;
        pointerData.position = currentPos;
        // 每帧触发拖拽事件
        ExecuteEvents.Execute(pointerData.pointerDrag, pointerData, ExecuteEvents.dragHandler);
        yield return null;
    }

    // 第三步:拖拽结束,触发结束事件和抬起操作
    ExecuteEvents.Execute(pointerData.pointerDrag, pointerData, ExecuteEvents.endDragHandler);
    pointerData.dragging = false;
    ProcessTouchPress(pointerData, pressed: false, released: true);
}

注意事项

  • 多触点模拟场景下,给不同的拖拽任务分配不同的pointerId即可,避免上下文冲突
  • 如果拖拽目标是ScrollRect等UGUI原生组件,需要保证按下位置的射线检测结果正确,没有被其他上层UI遮挡
  • 不需要自行重写ProcessDrag方法,直接复用UGUI原生事件执行逻辑兼容性更高

内容的提问来源于stack exchange,提问作者BadCoder010101

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 13:24:04