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

Unity安卓游戏触摸延迟:安卓库获取触摸数据遇监听器覆盖问题求助

解决Unity安卓触摸延迟的Android Library方案

首先,非常理解你从旧引擎迁移过来后遇到的触摸延迟问题——玩家的反馈确实是硬伤。你提到的两个思路里,轮询触摸数据在安卓系统里基本不可行(因为安卓触摸系统是纯事件驱动的,没有公开API支持主动查询当前触摸状态),所以重点放在第二个思路:代理原有触摸监听器或者通过事件分发拦截来获取数据,同时不影响Unity的触摸处理。

下面给你两个具体的可行方案,按推荐度排序:


方案1:自定义ViewGroup包裹Unity视图(无反射,更稳定)

这个方法不需要碰Unity原有的触摸监听器,而是通过在Unity视图外层套一个自定义的ViewGroup,在事件分发的过程中拦截并获取触摸数据,然后把事件原封不动传给Unity。

步骤1:创建自定义ViewGroup

public class TouchInterceptorLayout extends FrameLayout {
    public TouchInterceptorLayout(Context context) {
        super(context);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        // 在这里提取你需要的触摸数据
        float touchX = event.getX();
        float touchY = event.getY();
        int actionType = event.getAction();
        
        // 把数据回传给Unity,这里用UnitySendMessage示例(你也可以用其他通信方式)
        UnityPlayer.UnitySendMessage(
            "TouchDataReceiver", // Unity场景中接收数据的GameObject名称
            "OnAndroidTouchReceived", // 对应的C#方法名
            String.format("%.2f,%.2f,%d", touchX, touchY, actionType)
        );
        
        // 必须调用super,把事件传递给内部的Unity视图,保证Unity原生触摸不受影响
        return super.dispatchTouchEvent(event);
    }
}

步骤2:替换Unity视图的父容器

在你的Android Library初始化时,找到Unity的主视图,把它放到自定义的ViewGroup里:

public class TouchPlugin {
    public static void initTouchInterceptor() {
        Activity currentActivity = UnityPlayer.currentActivity;
        View unityView = currentActivity.mUnityPlayer.getView();
        ViewGroup originalParent = (ViewGroup) unityView.getParent();
        
        if (originalParent == null) return;
        
        // 移除Unity视图
        int viewIndex = originalParent.indexOfChild(unityView);
        originalParent.removeView(unityView);
        
        // 创建自定义布局并添加Unity视图
        TouchInterceptorLayout interceptorLayout = new TouchInterceptorLayout(currentActivity);
        interceptorLayout.addView(unityView);
        
        // 把拦截器布局放回原父容器的原位置
        originalParent.addView(interceptorLayout, viewIndex);
    }
}

方案2:反射获取原有触摸监听器并代理(需要处理反射权限)

如果因为某些原因不能修改视图层级,可以用反射获取Unity视图原本的OnTouchListener,然后设置自己的监听器,处理完数据后再调用原监听器的方法。

实现代码:

public class TouchListenerProxy {
    public static void setupProxy() {
        View unityView = UnityPlayer.currentActivity.mUnityPlayer.getView();
        
        try {
            // 反射获取View的私有字段mOnTouchListener
            Field touchListenerField = View.class.getDeclaredField("mOnTouchListener");
            touchListenerField.setAccessible(true);
            View.OnTouchListener originalListener = (View.OnTouchListener) touchListenerField.get(unityView);
            
            // 设置自己的监听器,代理原监听器
            unityView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    // 处理触摸数据,回传给Unity
                    float x = event.getX();
                    float y = event.getY();
                    int action = event.getAction();
                    UnityPlayer.UnitySendMessage("TouchDataReceiver", "OnAndroidTouchReceived", x + "," + y + "," + action);
                    
                    // 调用原监听器,保证Unity的触摸逻辑正常执行
                    if (originalListener != null) {
                        return originalListener.onTouch(v, event);
                    }
                    return false;
                }
            });
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
            // 反射失败的 fallback:可以考虑用方案1,或者提示错误
        }
    }
}

注意事项:

  • Android 12及以上版本可能对反射私有字段有更严格的限制,需要在Manifest中添加android:exported="true"(Unity打包时一般已经设置),或者考虑用方案1更稳妥。
  • 务必保证调用原监听器的onTouch方法,否则Unity的原生触摸事件会完全失效。

关于轮询思路的补充

安卓系统的触摸机制是基于事件回调的,没有官方API支持主动查询当前触摸状态(比如是否有手指按下、当前坐标等)。即使通过一些非公开的方法(比如读取/dev/input下的设备文件)获取触摸数据,不仅需要系统权限,还会引入新的延迟和兼容性问题,完全不推荐。

最后,不管用哪个方案,都要在不同安卓版本和设备上做测试,确保Unity的原生触摸和你的自定义触摸数据获取都正常工作,这样才能解决延迟问题的同时不影响玩家体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:24:43