Unity FPS相机按ESC切换后光标无法重新锁定隐藏问题
问题根源
- 现有代码仅在切换回锁定状态时设置了
Cursor.visible属性,解锁分支未显式指定光标可见性,完全依赖Unity引擎的自动切换行为,极易出现引擎层状态和业务逻辑不同步的问题。 - 直接读取
Cursor.lockState的实时返回值做切换判断可靠性差:游戏窗口失焦、系统弹窗弹出、编辑器环境操作都可能在底层修改光标锁定状态,导致分支判断失准、属性设置不生效。 - 未做光标状态的显式初始化,也没有处理窗口焦点恢复后的状态重置,逻辑容易被系统默认行为干扰。
修复方案
- 维护独立的布尔变量记录业务层预期的光标锁定状态,不直接依赖引擎返回的实时光标状态做逻辑判断
- 每次切换状态时同时显式设置
Cursor.lockState和Cursor.visible两个属性,锁定/解锁两个状态的属性都要明确赋值,不依赖引擎的自动补全逻辑 - 游戏启动初始化、窗口重新获得焦点时,主动按照业务层记录的状态重设光标属性,覆盖系统的默认修改
修复后的完整代码如下:
// 业务层维护的光标锁定标记,初始状态为锁定 private bool isCursorLocked = true; void Start() { // 启动时显式初始化光标状态,不依赖引擎默认值 UpdateCursorState(); } void Update() { HandleCursorToggle(); if (isCursorLocked) { LookAround(); } } void HandleCursorToggle() { if (Input.GetKeyDown(KeyCode.Escape)) { // 直接翻转业务层状态标记 isCursorLocked = !isCursorLocked; UpdateCursorState(); } } // 抽离统一的光标状态设置方法,避免漏写属性 void UpdateCursorState() { Cursor.lockState = isCursorLocked ? CursorLockMode.Locked : CursorLockMode.None; Cursor.visible = !isCursorLocked; } // 窗口重新获得焦点时强制重设光标,解决失焦导致的状态异常 private void OnApplicationFocus(bool hasFocus) { if (hasFocus) { UpdateCursorState(); } }
补充说明
- Unity编辑器环境下运行时,偶尔会因为编辑器自身的光标逻辑出现状态延迟,打包后运行逻辑会完全稳定。
- 如果需要解锁时光标不超出游戏窗口范围,可以将解锁状态对应的
CursorLockMode.None替换为CursorLockMode.Confined,按需调整即可。
内容的提问来源于stack exchange,提问作者Jenith S
相关产品推荐
相关产品推荐

