Windows上用于框架独立输入系统的Unity,setWindowsHook和多线程

时间:2019-04-24 12:20:48

标签: c# c++ windows multithreading unity3d


我想在Unity中实现独立于框架的触摸输入系统,以直接从Windows获取触摸事件。

我所做的是:

=>编写 C ++ 代码以在全局WM-Touch消息上设置Windows Hook。 (使用SetWindowsHookEx,并将线程ID = 0用于全局消息),将其编译为 DLL

Code based on this article

void DLL_initialize_hook(IntPtr window_handler)
{
    // <g_hInst> is the DLL handler
    // <HookProcPosted> and <HookProcCalled> are the functions
    // to filter and manage touch messages
    SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)HookProcPosted, g_hInst, 0);
    SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)HookProcCalled, g_hInst, 0);

    //register touch window to receive touch data as WM-Touch
    int fine_touch = 1;
    RegisterTouchWindow(window_handler, fine_touch );
}


=>使用 C# 创建 DLL_Interface Singleton 类以封装DLL中的函数。

void StartHook(IntPtr unity_window_handler )
{
  DLL_initialize_hook(unity_window_handler );
}

Touch[] getAllTouchData()
{
    //Actually there are more steps than just calling 2 function
    //that's why i wraped it
    TouchData[] data = DLL_getTouchData()
    return ConvertAllData(data );
}

=>在 中创建 新线程 (将其命名为 loop_thread ) Unity 使用 C# 使用DLL中的函数初始化Hook in loop_thread 以前编译过的(DLL初始化函数需要Unity窗口处理程序将其注册为触摸窗口:RegisterTouchWindow

//the function to run in the thread
void Thread_run()
{
    Thread_Initialize();
    Thread_Loop();
}

void Thread_Initialize()
{
    DLL_Interface.StarHook(unity_window_handler);
}

=> loop_thread从DLL以250Hz的频率拉动触摸事件(DLL仅输出新数据)

void Thread_Loop()
{
    while(running)
    {
        //Get the Touche data using a function from singleton interface
        List<Touch> touches = DLL_Interface.Instance.getAllTouchData();

        //Conversion and put the data available for Unity in a thread safe way
        ManageTheTouches(touches);

        //Wait next pull
        Thread.sleep(sleep_time)
    }
}

我想要的是 接收触摸输入,而不受Unity框架更新速率的限制

即使我 loop_thread 上的触摸消息初始化了一个全局钩子 ,并使用250Hz作为频率, 触摸输入速率仍然受到Unity帧更新速率的限制

Unity update rate is 30 Hz, touch input also limited at 30 Hz

Unity update rate is 60 Hz, touch input also limited at 60 Hz

为什么在loop_thread上初始化的Hook受Unity主线程的帧速率限制?

我有几个嫌疑犯:

=> RegisterTouchWindow 函数在发送WM-Touch消息之前正在等待Unity主线程的响应,这就是为什么我不能使用此函数绕过Unity的帧更新速率。

=> SetWindowHookEx 函数以某种方式注入代码以将消息过滤到Unity的主线程中,因此受Unity的主线程的帧速率限制。(在 文档 指出:“系统在挂钩应用程序的上下文中执行挂钩;特别是在名为SetWindowsHookEx的线程上执行)”

=>从loop_thread中的DLL调用钩子初始化函数不会将钩子安装在loop_thread上,而是安装在调用者的主线程(在本例中是Unity主线程?)上。

0 个答案:

没有答案