unity-raw-input icon indicating copy to clipboard operation
unity-raw-input copied to clipboard

Severe mouse slowdown/latency when my Unity app runs, but only on one computer, not another

Open eschewary opened this issue 3 years ago • 11 comments

I'm getting extremely slow, laggy, barely controllable mouse movement when my Unity build is running. When I run the same app on my older computers however, it runs perfectly.

The mouse movement is better when over the Unity app window, but still slow.

I've narrowed it down to the RawInput code, but again, only one machine runs it slow; the other two (substantially weaker) machines run it with RawInput perfectly.

I've tried to illustrate the difference in mouse control by drawing little circles, first inside the Unity app window, the outside. The RawInput script is inactive in the first gif, active in the second. You can see in the second how the mouse goes flying off at the end, this is a result of the latency. How can I narrow down the cause?

rawNoLag

rawLag

eschewary avatar Nov 04 '22 21:11 eschewary

Make sure run in background is enabled in build settings.

elringus avatar Nov 05 '22 15:11 elringus

Yes, run in background is enabled for my project:

image

Any other suggestions I should check, or specific code I can test?

eschewary avatar Nov 05 '22 20:11 eschewary

This could be related with mouse sampling rate (DPI). The hooks are invoked for each position change and with high rate it could be slow due to native (c++) -> managed (c#) callbacks. We actually don't need to sample mouse movement, but I'm not sure if it's possible to opt-out of this.

elringus avatar Nov 05 '22 21:11 elringus

Ok, I tried changing the DPI with my mouse buttons with no change. Thanks for the suggestion, let me know if you think of anything else I can try. Just strange it only affects my most powerful machine... 🤔

eschewary avatar Nov 05 '22 22:11 eschewary

Try removing the mouse hook to check whether it's related with mouse at all: https://github.com/Elringus/UnityRawInput/blob/master/Assets/UnityRawInput/Runtime/RawInput.cs#L75

elringus avatar Nov 05 '22 22:11 elringus

I'm having the same problem, when I try to run my unity application at low framerates to save GPU usage, it ends up affecting the mouse. It seems like the fps is limiting how many times per second the mouse is allowed to update/move. Its working fine when I'm using the app in the unity editor, its only when I make a final build that I'm having problems. And yes removing the mouse hook removes the mouse lag, but then I'm not able to detect mouse clicks anymore.

WhyV77 avatar Nov 07 '22 22:11 WhyV77

Weird that FPS cap is affecting this. The hook processing shouldn't depend on Unity's render loop in any way.

Ideally we would opt-out of receiving mouse position callbacks, but not sure if that's possible.

elringus avatar Nov 07 '22 23:11 elringus

For now I will just manually set the framerate to something higher while I'm checking for Raw Input over a button, but I would love a better solution, since this makes the GPU usage of the application go from 1.5% to 10-15%.

WhyV77 avatar Nov 08 '22 00:11 WhyV77

Thank you guys! I set my project to sync every V-blank and it resolved the mouse lag. As far as I'm concerned this issue can be resolved. Should I close it?

eschewary avatar Nov 08 '22 01:11 eschewary

sync every V-blank and it resolved the mouse lag

So it looks like the render loop is actually affecting input hook procs (or vice versa).

Let's keep the issue open; maybe someone will figure how to solve this or at least why this is happening.

elringus avatar Nov 08 '22 10:11 elringus

The slowdown happens because hooks are processed on Unity's main thread. The best practice is to spawn a separate thread to handle the event loop like described here: https://stackoverflow.com/a/52201983 Alternatively you can also change HookType.WH_MOUSE_LL to HookType.WH_MOUSE in the RawInput class. Personally, since I only needed to catch the mouse events in the editor itself, and not outside of it, I've changed the SetHooks method to look like this:

private static void SetHooks ()
{
    uint threadId = Win32API.GetCurrentThreadId();
    hooks.Add(Win32API.SetWindowsHookEx(HookType.WH_KEYBOARD, HandleKeyboardProc, IntPtr.Zero, threadId));
    hooks.Add(Win32API.SetWindowsHookEx(HookType.WH_MOUSE, HandleMouseProc, IntPtr.Zero, threadId));
}

This limits the amount of processing needed to a point where no separate thread is needed. Of course my change is useless for people who need actual global events, but this helped with lag in my case so I'll leave it at that.

4as avatar Oct 24 '24 16:10 4as