Search Unity

Issue with CursorLockMode.Locked

Discussion in 'Input System' started by P0150N, Apr 11, 2020.

  1. P0150N

    P0150N

    Joined:
    Aug 1, 2015
    Posts:
    9
    I am having issues when setting the Cursor.lockState to CursorLockMode.Locked.

    The issue is when this is enabled, the input manager doesn't recognize cursor movements within the window, so it always prints (0,0) when I print the debug.

    But, when I press "Escape", and the cursor is freed, it suddenly recognizes the cursor and prints the correct delta in the console.

    Anybody else having issues with this?

    I am using the Linux editor, if that is relevant.

    I have attached a screenshot of my input controls setup.
     

    Attached Files:

  2. IgnisIncendio

    IgnisIncendio

    Joined:
    Aug 16, 2017
    Posts:
    223
    I'm using Input System, Cursor locked and a mouse binding with a Vector2 InputAction. I read the values using ReadValue<Vector2>() with Player Input, using C# events and onActionCallback. I'm not experiencing the issue that you have currently.

    Maybe it's related to the Linux editor? Does it work in build?

    Edit: I just noticed you're using Delta Pointer. I'm using Delta Mouse. Maybe that's the problem?

     
  3. P0150N

    P0150N

    Joined:
    Aug 1, 2015
    Posts:
    9
    Hey, thanks for the reply.

    I was using the same configuration on my Mac a couple of months ago and it was working, it was when I switched to Linux that it doesn't work anymore, so it might be the Linux editor.

    Also, something I noticed is when I click the dropdown, I see the delta [Mouse] option, but it's blanked out for me. I can't select it with the mouse, but I can use the arrow keys on my keyboard and press "Enter", which selects the option. Issue still occurs when using that option though.


    I read my values a little differently. I'm trying to go full ECS, but since the Input system doesn't really support it, I wrote some code to integrate it better.

    I marked my Input asset as an "Addressable", and then load it at runtime. From there, I read all the necessary values.

    Here's a snippet:

    Code (CSharp):
    1.  public class PlayerInputSystem : SystemBase
    2.     {
    3.         private InputAction m_Movement;
    4.         private InputAction m_Look;
    5.  
    6.         protected override void OnCreate()
    7.         {
    8.             InputSystem.settings.updateMode = InputSettings.UpdateMode.ProcessEventsManually;
    9.  
    10.             Addressables.LoadAssetsAsync<InputActionAsset>("Input", input =>
    11.             {
    12.                 input.Enable();
    13.  
    14.                 var playerMap = input.FindActionMap("Player");
    15.  
    16.                 m_Movement = playerMap.FindAction("Move");
    17.  
    18.                 m_Look = playerMap.FindAction("Look");
    19.  
    20.                 m_Look.Enable();
    21.             });
    22.         }
    23.  
    24.         protected override void OnUpdate()
    25.         {
    26.             InputSystem.Update();
    27.  
    28.             if (m_Movement == null || m_Look == null)
    29.                 return;
    30.  
    31.             var movement = m_Movement.ReadValue<Vector2>();
    32.  
    33.             var look = m_Look.ReadValue<Vector2>();
    34.  
    35.             // look and movement
    36.             Entities
    37.                 .WithNone<CameraLockComponent, CharacterLockComponent>()
    38.                 .WithAll<PhysicalPlayer>()
    39.                 .ForEach((ref CharacterControllerInternalData internalData) =>
    40.                 {
    41.                     internalData.Input.Movement.x = movement.x;
    42.                     internalData.Input.Movement.y = movement.y;
    43.                     internalData.Input.Looking.x = look.x;
    44.                     internalData.Input.Looking.y = look.y;
    45.                 })
    46.                 .Schedule();
    47.         }
    The issue shouldn't be the fact that I'm using ECS, since it is when I do a Debug.Log(m_Look), it prints as (0,0), and then only prints the deltas when I free the cursor.
     
  4. IgnisIncendio

    IgnisIncendio

    Joined:
    Aug 16, 2017
    Posts:
    223
    Hmm, could it be due to UpdateMode.ProcessEventsManually? What if you do it with automatic updates?

    Also yeah, I think it could be a Linux-specific issue, since it's related to the OS mouse/pointer API.
     
  5. transat

    transat

    Joined:
    May 5, 2018
    Posts:
    779
    Oh this is interesting. Is the new input system otherwise working fine in DOTS with your integration?
     
  6. IAndrewNovak

    IAndrewNovak

    Joined:
    Nov 29, 2013
    Posts:
    118
    Same issue on old and new input systems. I rewrote the old system to cast ray from the center of the screen.
    In the new system, I can't rewrite EventSystem because not all functions are virtual and inheritances Editor are broken :(
     
  7. P0150N

    P0150N

    Joined:
    Aug 1, 2015
    Posts:
    9
    Really depends on what you want to do.

    If you're capturing keystrokes like Mouse Down, I don't approach it in the traditional OOP way where you have something like a callback, and that callback does something (technically you can do it this way - you would call your EntityManager and do some work), but I'm trying to stick to DOTS as much as I can.

    Basically, for something simple like keystrokes, I have two systems, one that captures a key press such as "E" to use ( or something like that), and record it onto the player controller from that same system I showed above, by setting the value to "1". The next system resets the value to "0", and if you want to capture that keystroke, you order your capturing system so that it's in the middle of the two systems. Visual example:

    - System 1 Captures Keystroke (sets value to 1)

    - System 2 Checks if Keystroke is 1, does something

    - System 3 Resets the Keystroke to 0.

    I haven't gone much further than that, but it's how I have approached doing key binds in DOTS, while trying to stay away from callbacks.

    I believe all of these have to also run on the main thread, so you can't use something like a Burst job for these systems.
     
    transat likes this.
  8. P0150N

    P0150N

    Joined:
    Aug 1, 2015
    Posts:
    9
    For this issue specifically, I can successfully capture "Mouse X" and "Mouse Y" without a problem. It seems to be that only the new input system can't capture the Mouse Delta when locked on Linux. For now, I'm using the legacy values (Input.GetAxis("Mouse X")) until this is patched.
     
  9. Kettle3D

    Kettle3D

    Joined:
    Jun 2, 2020
    Posts:
    2
    I have a problem with my game as well -- When I use
    UnityEngine.Cursor.LockState = CursorLockMode.Locked;
    it keeps the cursor in the middle of the screen on Windows, but in Linux it still moves around. I think it is something to do with running it on Linux -- it happens in the editor and in build mode.
     
  10. FlavioIT

    FlavioIT

    Joined:
    Apr 20, 2015
    Posts:
    4
    @Rene-Damm
    I have the same problem, everything is working fine without the cursor locked. Once locked the delta is 0,0.
    Probably once locked we should use another way, I wonder.
    from https://docs.unity3d.com/Packages/com.unity.inputsystem@1.1/manual/Pointers.html
    delta Vector2Control The difference in position since the last frame.
    Maybe because locked means the pointer at the center, even if the mouse is moved, we don't get any data.
    Tried Position[Mouse], same behaviour.
    Action is a Value and Control a Vector2 (for borh Position and Delta)
    What is it the intended behaviour?
     
    Last edited: Sep 8, 2020
  11. Chris_Entropy

    Chris_Entropy

    Joined:
    Apr 11, 2011
    Posts:
    202
    I am having the same problem, also in the Linux Editor. I will stick to the old input system until this is fixed.
     
  12. bryaaaan

    bryaaaan

    Joined:
    Dec 23, 2020
    Posts:
    1
    Is there any update on this issue? Reverting to the old input system isn't an option for me. I'm using 2020.2.3f1.

    I've tried two things so far:
    • Reading the current mouse delta x, y during Update(). When the cursor is locked, this always returns (0, 0). If I release the cursor by pressing ESC, the delta will start changing
    • Firing an event on delta mouse to capture the value and then read those values on Update(). The values in the event fire, but Update() doesn't get the same value if the cursor is locked.

      Code (CSharp):
      1. ...
      2. public CharacterController controller;
      3. float cl_cursor_x = 0.0f;
      4. ...
      5. void Start() {
      6.   Cursor.lockState = CursorLockMode.Locked;
      7. }
      8.  
      9. void Update() {
      10.   Debug.Log(cl_mouse_x);
      11.   controller.transform.Rotate(new Vector3(0, cl_mouse_x, 0));
      12. }
      13.  
      14. public void OnLook(InputAction.CallbackContext context) {
      15.   var val = context.ReadValue<Vector2>();
      16.   Debug.Log(val);
      17.   cl_mouse_x = val.x;
      18. }
    This only rotates if Cursor.lockState isn't Locked.
     
  13. Lukas_Schwarz

    Lukas_Schwarz

    Joined:
    Aug 3, 2013
    Posts:
    7
    Last edited: Jun 24, 2021