using System.Linq; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; namespace RR.Common.Utility { public class AutoCursorHider : MonoBehaviour { [Header("Поведение")] [Tooltip("Сколько секунд после движения мыши держать курсор видимым")] public float mouseVisibleHold = 1.0f; [Tooltip("Блокировать ли курсор, когда он скрыт (Locked)")] public bool lockWhenHidden = false; [Tooltip("Начинать со скрытого курсора")] public bool startHidden = true; private float _lastMouseMoveTime = -999f; private bool _visible; private void Awake() { SetCursorVisible(!startHidden); } private void Update() { bool mouseMoved = WasMouseMovedOrClickedThisFrame(); if (mouseMoved) _lastMouseMoveTime = Time.unscaledTime; bool nonPointerInput = WasKeyboardOrGamepadThisFrame(); // Показать курсор сразу при движении мыши if (mouseMoved && !_visible) SetCursorVisible(true); // Скрыть курсор при управлении клавишами/геймпадом if (nonPointerInput && _visible) SetCursorVisible(false); // Если мышь не трогали какое-то время — можно снова спрятать (опционально) if (_visible && !mouseMoved && (Time.unscaledTime - _lastMouseMoveTime) > mouseVisibleHold && nonPointerInput) SetCursorVisible(false); } private void SetCursorVisible(bool show) { if (_visible == show) return; _visible = show; Cursor.visible = show; Cursor.lockState = show ? CursorLockMode.None : (lockWhenHidden ? CursorLockMode.Locked : CursorLockMode.None); // Совет: для UI-меню лучше Confined вместо Locked, если хочется скрыть не блокируя: // Cursor.lockState = show ? CursorLockMode.None : CursorLockMode.Confined; } private static bool WasMouseMovedOrClickedThisFrame() { if (Mouse.current == null) return false; if (Mouse.current.delta.ReadValue().sqrMagnitude > 0) return true; if (Mouse.current.scroll.ReadValue().y != 0) return true; return Mouse.current.leftButton.wasPressedThisFrame || Mouse.current.rightButton.wasPressedThisFrame || Mouse.current.middleButton.wasPressedThisFrame; } private static bool WasKeyboardOrGamepadThisFrame() { bool kb = Keyboard.current != null && Keyboard.current.anyKey.isPressed; bool gp = Gamepad.current != null && Gamepad.current.allControls.Any(c => c is ButtonControl { wasPressedThisFrame: true }); return kb || gp; } // Публичные методы, если нужно управлять вручную public void ForceShowCursor() => SetCursorVisible(true); public void ForceHideCursor() => SetCursorVisible(false); } }