chunk 1: core gameplay scripts scenes runtime assets
This commit is contained in:
203
Assets/Scripts/Camera/CinemachineCameraInput.cs
Normal file
203
Assets/Scripts/Camera/CinemachineCameraInput.cs
Normal file
@@ -0,0 +1,203 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.InputSystem;
|
||||
using Cinemachine;
|
||||
|
||||
/// <summary>
|
||||
/// Custom Cinemachine input handler that replaces CinemachineInputProvider.
|
||||
/// Uses CinemachineCore.GetInputAxis delegate for total control over camera orbit.
|
||||
///
|
||||
/// Supports:
|
||||
/// - Gamepad right stick (X = horizontal orbit, Y = vertical orbit)
|
||||
/// - Mobile touch drag (right half of screen, ignoring UI)
|
||||
/// - Mouse delta (desktop/editor)
|
||||
///
|
||||
/// Attach this to the CinemachineFreeLook camera GameObject.
|
||||
/// Remove or disable CinemachineInputProvider if present.
|
||||
/// </summary>
|
||||
public class CinemachineCameraInput : MonoBehaviour
|
||||
{
|
||||
[Header("Sensitivity")]
|
||||
[SerializeField] private float gamepadSensitivityX = 200f;
|
||||
[SerializeField] private float gamepadSensitivityY = 3f;
|
||||
[SerializeField] private float touchSensitivityX = 0.15f;
|
||||
[SerializeField] private float touchSensitivityY = 0.003f;
|
||||
[SerializeField] private float mouseSensitivityX = 3f;
|
||||
[SerializeField] private float mouseSensitivityY = 0.03f;
|
||||
|
||||
[Header("Touch Settings")]
|
||||
[Tooltip("Only process touches on the right portion of the screen (0.5 = right half)")]
|
||||
[Range(0f, 1f)]
|
||||
[SerializeField] private float touchActiveScreenRatio = 0.4f;
|
||||
|
||||
[Tooltip("Ignore touches over UI elements (buttons, joysticks, etc.)")]
|
||||
[SerializeField] private bool ignoreUITouches = true;
|
||||
|
||||
[Header("Filtering")]
|
||||
[SerializeField] private float stickDeadzone = 0.15f;
|
||||
[SerializeField] private float smoothing = 0.1f;
|
||||
|
||||
// Touch tracking
|
||||
private int activeTouchId = -1;
|
||||
private Vector2 lastTouchPos;
|
||||
|
||||
// Smoothed output
|
||||
private float smoothedX;
|
||||
private float smoothedY;
|
||||
private float rawX;
|
||||
private float rawY;
|
||||
|
||||
// Axis names used by CinemachineFreeLook
|
||||
private const string XAxisName = "Mouse X";
|
||||
private const string YAxisName = "Mouse Y";
|
||||
|
||||
private CinemachineFreeLook freeLookCam;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
freeLookCam = GetComponent<CinemachineFreeLook>();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
// Override Cinemachine's input gathering with our custom handler
|
||||
CinemachineCore.GetInputAxis = HandleCinemachineInput;
|
||||
|
||||
// Disable CinemachineInputProvider if present (we replace it)
|
||||
var provider = GetComponent<CinemachineInputProvider>();
|
||||
if (provider != null)
|
||||
{
|
||||
provider.enabled = false;
|
||||
Debug.Log("[CinemachineCameraInput] Disabled CinemachineInputProvider — using custom input handler");
|
||||
}
|
||||
|
||||
// Clear the default input axis names on the FreeLook camera
|
||||
// This prevents Cinemachine from also reading legacy Input Manager axes
|
||||
if (freeLookCam != null)
|
||||
{
|
||||
freeLookCam.m_XAxis.m_InputAxisName = "";
|
||||
freeLookCam.m_YAxis.m_InputAxisName = "";
|
||||
}
|
||||
|
||||
Debug.Log("[CinemachineCameraInput] Custom camera input enabled (gamepad + touch + mouse)");
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
// Restore default input handling when disabled
|
||||
CinemachineCore.GetInputAxis = UnityEngine.Input.GetAxis;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// Gather raw input from all sources
|
||||
rawX = 0f;
|
||||
rawY = 0f;
|
||||
|
||||
ReadGamepadInput();
|
||||
ReadTouchInput();
|
||||
ReadMouseInput();
|
||||
|
||||
// Smooth the input
|
||||
if (smoothing > 0.001f)
|
||||
{
|
||||
smoothedX = Mathf.Lerp(smoothedX, rawX, Time.unscaledDeltaTime / smoothing);
|
||||
smoothedY = Mathf.Lerp(smoothedY, rawY, Time.unscaledDeltaTime / smoothing);
|
||||
}
|
||||
else
|
||||
{
|
||||
smoothedX = rawX;
|
||||
smoothedY = rawY;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delegate callback — Cinemachine calls this instead of Input.GetAxis
|
||||
/// </summary>
|
||||
private float HandleCinemachineInput(string axisName)
|
||||
{
|
||||
if (axisName == XAxisName) return smoothedX;
|
||||
if (axisName == YAxisName) return smoothedY;
|
||||
return 0f;
|
||||
}
|
||||
|
||||
// ======================== GAMEPAD ========================
|
||||
private void ReadGamepadInput()
|
||||
{
|
||||
if (Gamepad.current == null) return;
|
||||
|
||||
Vector2 rightStick = Gamepad.current.rightStick.ReadValue();
|
||||
|
||||
// Apply deadzone
|
||||
if (rightStick.magnitude < stickDeadzone)
|
||||
return;
|
||||
|
||||
rawX += rightStick.x * gamepadSensitivityX * Time.unscaledDeltaTime;
|
||||
rawY += rightStick.y * gamepadSensitivityY * Time.unscaledDeltaTime;
|
||||
}
|
||||
|
||||
// ======================== TOUCH ========================
|
||||
private void ReadTouchInput()
|
||||
{
|
||||
if (Touchscreen.current == null) return;
|
||||
|
||||
var touches = Touchscreen.current.touches;
|
||||
bool foundActiveTouch = false;
|
||||
|
||||
for (int i = 0; i < touches.Count; i++)
|
||||
{
|
||||
var touch = touches[i];
|
||||
if (!touch.press.isPressed) continue;
|
||||
|
||||
int id = touch.touchId.ReadValue();
|
||||
Vector2 pos = touch.position.ReadValue();
|
||||
|
||||
// If no active touch, try to start tracking this one
|
||||
if (activeTouchId == -1)
|
||||
{
|
||||
// Only track touches on the right portion of the screen
|
||||
if (pos.x < Screen.width * touchActiveScreenRatio)
|
||||
continue;
|
||||
|
||||
// Ignore touches over UI elements
|
||||
if (ignoreUITouches && EventSystem.current != null &&
|
||||
EventSystem.current.IsPointerOverGameObject(id))
|
||||
continue;
|
||||
|
||||
activeTouchId = id;
|
||||
lastTouchPos = pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (touch.touchId.ReadValue() != activeTouchId)
|
||||
continue;
|
||||
|
||||
foundActiveTouch = true;
|
||||
Vector2 delta = pos - lastTouchPos;
|
||||
lastTouchPos = pos;
|
||||
|
||||
rawX += delta.x * touchSensitivityX;
|
||||
rawY += delta.y * touchSensitivityY;
|
||||
}
|
||||
|
||||
// Reset tracking if active touch released
|
||||
if (activeTouchId != -1 && !foundActiveTouch)
|
||||
{
|
||||
activeTouchId = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// ======================== MOUSE ========================
|
||||
private void ReadMouseInput()
|
||||
{
|
||||
if (Mouse.current == null) return;
|
||||
|
||||
// Only use mouse if right button is held (prevents accidental camera rotation)
|
||||
if (!Mouse.current.rightButton.isPressed) return;
|
||||
|
||||
Vector2 mouseDelta = Mouse.current.delta.ReadValue();
|
||||
|
||||
rawX += mouseDelta.x * mouseSensitivityX * Time.unscaledDeltaTime;
|
||||
rawY += mouseDelta.y * mouseSensitivityY * Time.unscaledDeltaTime;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user