79 lines
3.1 KiB
C#
79 lines
3.1 KiB
C#
using System.Linq;
|
||
using UnityEngine;
|
||
using UnityEngine.InputSystem;
|
||
using UnityEngine.InputSystem.Controls;
|
||
|
||
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);
|
||
}
|