Cursor lock after regaining focus - Unity 2018.1.0f2

I have an in-game menu that I load when pressing escape that pauses the game, makes the cursor visible, and sets its restriction to none so users can freely click in other windows outside of the game if need be. It also auto pauses when the window loses focus.

When you press escape or the resume button, the cursor locks again and goes invisible.

Everything behaves as I want except when the game window loses focus. Once I regain focus back into the game window and resume the game the cursor is hidden but not locked. The game still works as usual, but I can see the cursor leave the window while looking around which, if you click on something in the game, will register as a click outside the window losing focus. For some reason, my cursor lock works fine in every case up until I lose focus and regain focus. I’m not sure what I’m missing. The cursor code is pretty straight forward.

            Cursor.visible = !Cursor.visible;
            //If the options menu has been closed, lock the mouse. Otherwise, unlock it
            if (optionsPanelToggle == false)
            {
                Cursor.lockState = CursorLockMode.Locked;
            }
            else
            {
                Cursor.lockState = CursorLockMode.None;
            }

This locks the cursor in place when I close the menu. However, after focus is lost then re-gained, when I close the menu it doesn’t lock.

I seem to have found a solution Basically when you lose focus of the program, windows sort of takes over cursor behavior again and Unity’s cursor lock doesn’t actually regain control after that. So I found you basically have to set the cursor position yourself after regaining focus.


I ended up working with a free unity asset that lets you read and set the cursor value for both local and global cursor positions in windows. I didn’t want to import a windows dll and basically build cursor tracking from scratch just so I could set the position and this was free.


Cursor Control


So what I ended up doing was recording the global cursor position once the player clicks the resume button in the pause menu. This makes sure the cursor is within the game window without extra code to detect it and the player can relocated the window to any display location across multiple displays.


It feels a bit rough doing it this way, but it’s the best solution I have found so far. After I get the position on resume, I throw that cursor location in update to keep it there. Everything works correctly so far.

 Vector2 _cursorForcePos;

//If the game has been resumed, set time and record the cursor's global position

        if (optionsPanelToggle == false)
        {
            _cursorForcePos = CursorControl.GetGlobalCursorPos();
            Time.timeScale = 1;
        }

    private void Update()
    {

// Check if the player is using a terminal and if the pause menu has been deactivated.

        if (CamManager.Ins.terminalUse == false && optionsPanelToggle == false)
        {

            CursorControl.SetGlobalCursorPos(_cursorForcePos);
        }
}