Search Unity

Event based mouse input handling for minimal input lag?

Discussion in 'Input System' started by Crayz, Feb 28, 2020.

  1. Crayz

    Crayz

    Joined:
    Mar 17, 2014
    Posts:
    194
    My goal is to reduce input lag as much as possible, I'm hoping event based input will help. I am currently using Mouse.current.delta in Update to update the player's view angles, but it still feels like there is a very small amount of input lag in comparison to Counter Strike.

    Code (CSharp):
    1. private void Update()
    2. {
    3.     // Attempt 1, smooth/consistent but minor input lag
    4.     var delta = Mouse.current.delta;
    5.     ProcessMouseLook(delta.x, delta.y);
    6. }
    7.  
    8. private void Start()
    9. {
    10.     var action = new InputAction(type: InputActionType.Value, binding: "<Mouse>/delta");
    11.     // Attempt 2, inconsistent/jumpy but improved input lag
    12.     action.performed += (ctx) =>
    13.     {
    14.         var delta = obj.ReadValue<Vector2>();
    15.         ProcessMouseLook(delta.x, delta.y);
    16.     };
    17.     action.Enable();
    18. }
    19.  
    20. private void ProcessMouseLook(float x, float y)
    21. {
    22.     var mx = x * xsens * .1f;
    23.     var my = y * ysens * .1f;
    24.     var rot = _player.angles + new Vector3(-my, mx, 0f);
    25.     rot.x = ClampAngle(rot.x, -89f, 89f);
    26.     _player.angles = rot;
    27. }
    28.  
    Is there a proper way to implement event based mouse input?
     
  2. Sal_Dev

    Sal_Dev

    Joined:
    Nov 4, 2015
    Posts:
    6
    Hey,
    excuse me to piggyback your thread from other aspects, as this common usage in most mobile games,
    what is the best method (polling or event based) to track mouse/touch movement?
    considering
    - player experience/smoothness/delay
    - performance
    - code & design: if there need to handle different gestures (swipe, tap, etc..)

    Thans
     
  3. print_helloworld

    print_helloworld

    Joined:
    Nov 14, 2016
    Posts:
    231
    You could try and poll in OnGUI instead of Update, as it can run more frequently. This was the way I got minimal input lag with the old input system.
     
  4. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    @Crayz note that attempt #1 and attempt #2 aren't strictly equivalent.

    With attempt #1 and Mouse.current.delta you're looking at the final, frame-accumulated value of the mouse delta. I.e. you query the final value once no matter how many changes there were to the delta within the frame.

    With attempt #2 and InputActions, you're looking at a change-to-change notification in the callback. Meaning that if, say, there's 10 delta changes in the frame, you get 10 calls to ProcessMouseLook. And accumulation still happens. Meaning that the second call, for example, is an accumulation of the first and the second delta. And so on.

    This gives deltas very quirky behavior in combination with actions. The accumulation is something that you generally want with polling-style APIs yet don't necessarily want with the callback API. I hope that in the future we have a more elegant setup for this than we do currently.

    The reason that input lag in #2 is slightly lower than #1 is that the callbacks run within input updates which happen *before* Updates/FixedUpdates are run. So you're closer in time to when the event was picked up from the OS.

    In general, the earliest point in time you can see the input is InputSystem.onEvent which runs from directly within the input processing loop. InputActions run within the same loop and are thus pretty much as close as InputSystem.onEvent.

    Overall, for mouse input, there's no way ATM to further minimize lag as the point where we pick up events from the OS and the point where we process input is currently fixed. So beyond picking up input during input processing instead of during MonoBehaviour updates, it's down to keeping framerate up.
     
  5. Crayz

    Crayz

    Joined:
    Mar 17, 2014
    Posts:
    194
    Thanks for the information. I've done some scouring and it seems fetching raw device input at the moment is very complicated, most solutions point to creating a window process to hook into the WM_INPUT message then pipe the information to Unity. Is there any chance Unity will provide a raw input option in the future?
     
  6. Querke

    Querke

    Joined:
    Feb 21, 2013
    Posts:
    54
    Resurrecting an old post :D

    From my readings, my unity game has the same/better input delay as counter strike source. Might be faulty readings somehow, but if that's the case, I don't know how.

    Captured with 480fps slow motion camera (oneplus 7t)
    The fps in my game was NOT capped with Application.targetFrameRate, but capped by adding higher demanding visuals (rendering takes longer).
    Both CSS and my game has the same options: Exclusive fullscreen, no vsync
    CSS uses "raw input" option in mouse settings.

    Tested both normal mouse.delta reading in Update() and mouse delta event callback.
    Mouse delta event callback might be faster, BUT it's very jittery and inconsistent (like OP said). To fix it, I let it accumulate to next Update

    Input delay really depends on framerate.

    Attempt 1 = normal mouse delta reading in update
    Attempt 2 = Using raw mouse delta event callback, accumulated until next Update() frame, then applied (to fix jitter)

    My game, 34fps
    1: 67 slow motion camera frames
    2: 72 slow motion camera frames

    My game, 120fps
    1: 22 slow motion camera frames
    2: 24 slow motion camera frames

    My game, 240fps
    1: 13 slow motion camera frames
    2: 14 slow motion camera frames

    My game, 293fps
    1: 6 slow motion camera frames
    2: 8 slow motion camera frames

    Counter strike Source, 290fps (3 attempts):
    a: 8 slow motion camera frames
    b: 9 slow motion camera frames
    c: 8 slow motion camera frames
     
    Crayz likes this.