Unity Cursor Lock Issue: Cursor Hidden but Can Click Outside Window

I’m facing a cursor locking issue in Unity that’s consistent in both the editor and the built version. The cursor hides as expected, but I can still click on external objects like desktop icons or Unity’s Inspector without pressing escape, effectively escaping the game window. Here’s my code:

private List<object> _cursorLockers = new();

public void SetCursorFree(object locker, bool state)
{
    if (state)
    {
        if (!_cursorLockers.Contains(locker))
            _cursorLockers.Add(locker);
    }
    else
    {
        if (_cursorLockers.Contains(locker))
            _cursorLockers.Remove(locker);
    }

    if (IsCursorLocked)
    {
        Cursor.lockState = CursorLockMode.Locked;
    }
    else
    {
        Cursor.lockState = CursorLockMode.None;
    }
}
public bool IsCursorLocked { get { return _cursorLockers.Count == 0; } }

This works perfectly on my laptop but fails on my PC. The problem persists even after building the game. Any help would be greatly appreciated.

1 Like

This is how it was in the old version of the Unity’s Starter Assets. I believe that the new version in the asset store also will have operating with that.

I use SetCursorLock(false); in the my Throw Control asset in FPS Demo when exiting a Demo Scene to go to the Menu Scene.

using System;
using UnityEngine;

namespace UnityStandardAssets.Characters.FirstPerson
{
    [Serializable]
    public class MouseLook
    {
        public float XSensitivity = 2f;
        public float YSensitivity = 2f;
        public bool clampVerticalRotation = true;
        public float MinimumX = -90F;
        public float MaximumX = 90F;
        public bool smooth;
        public float smoothTime = 5f;
        public bool lockCursor = true;


        private Quaternion m_CharacterTargetRot;
        private Quaternion m_CameraTargetRot;
        private bool m_cursorIsLocked = true;

        public void Init(Transform character, Transform camera)
        {
            m_CharacterTargetRot = character.localRotation;
            m_CameraTargetRot = camera.localRotation;
        }


        public void LookRotation(Transform character, Transform camera)
        {
            float yRot = Input.GetAxis("Mouse X") * XSensitivity;
            float xRot = Input.GetAxis("Mouse Y") * YSensitivity;

            m_CharacterTargetRot *= Quaternion.Euler (0f, yRot, 0f);
            m_CameraTargetRot *= Quaternion.Euler (-xRot, 0f, 0f);

            if(clampVerticalRotation)
                m_CameraTargetRot = ClampRotationAroundXAxis (m_CameraTargetRot);

            if(smooth)
            {
                character.localRotation = Quaternion.Slerp (character.localRotation, m_CharacterTargetRot,
                    smoothTime * Time.deltaTime);
                camera.localRotation = Quaternion.Slerp (camera.localRotation, m_CameraTargetRot,
                    smoothTime * Time.deltaTime);
            }
            else
            {
                character.localRotation = m_CharacterTargetRot;
                camera.localRotation = m_CameraTargetRot;
            }

            UpdateCursorLock();
        }

        public void SetCursorLock(bool value)
        {
            lockCursor = value;
            if(!lockCursor)
            {//we force unlock the cursor if the user disable the cursor locking helper
                Cursor.lockState = CursorLockMode.None;
                Cursor.visible = true;
            }
        }

        public void UpdateCursorLock()
        {
            //if the user set "lockCursor" we check & properly lock the cursos
            if (lockCursor)
                InternalLockUpdate();
        }

        private void InternalLockUpdate()
        {
            if(Input.GetKeyUp(KeyCode.Escape))
            {
                m_cursorIsLocked = false;
            }
            else if(Input.GetMouseButtonUp(0))
            {
                m_cursorIsLocked = true;
            }

            if (m_cursorIsLocked)
            {
                Cursor.lockState = CursorLockMode.Locked;
                Cursor.visible = false;
            }
            else if (!m_cursorIsLocked)
            {
                Cursor.lockState = CursorLockMode.None;
                Cursor.visible = true;
            }
        }

        Quaternion ClampRotationAroundXAxis(Quaternion q)
        {
            q.x /= q.w;
            q.y /= q.w;
            q.z /= q.w;
            q.w = 1.0f;

            float angleX = 2.0f * Mathf.Rad2Deg * Mathf.Atan (q.x);

            angleX = Mathf.Clamp (angleX, MinimumX, MaximumX);

            q.x = Mathf.Tan (0.5f * Mathf.Deg2Rad * angleX);

            return q;
        }

    }
}

using System;
using UnityEngine;

namespace UnityStandardAssets.Characters.FirstPerson
{
    public class FirstPersonController : MonoBehaviour
    {
        [SerializeField] private MouseLook m_MouseLook;
        
        private void Start()
        {
			m_MouseLook.Init(transform , m_Camera.transform);
        }

        private void Update()
        {
            m_MouseLook.LookRotation(transform, m_Camera.transform);
        }

        private void FixedUpdate()
        {
            m_MouseLook.UpdateCursorLock();
        }

        public void SetCursorLock(bool value)
        {
            m_MouseLook.SetCursorLock(value);
        }
    }
}

Even if i constantly lock the cursor in the update, it still only hides and not locks.

1 Like

What is your exact Unity version?
What are the differences between your PC and a Laptop?

I am using version 2022.3.49f1.
The main difference between my computers that can have an impact on this problem is that my PC has dual monitor setup.
But i have tried deactivating my second monitor and the problem remained.
Also this problem started today, it used to work on both copmuters.

1 Like

Hi, omayunay. This looks like a bug. Could you please report a bug via the Bug Reporter (“Help → Report a Bug…” in the Unity Editor)? Make sure to do that while having your problematic project open. This way it will be attached to the report. Cheers!

1 Like