using UnityEngine; using UnityEngine.InputSystem; using System; public class InputManager : MonoBehaviour { private static InputManager _instance; public static InputManager Instance { get { if (_instance == null) { _instance = FindAnyObjectByType(); if (_instance == null) { var go = new GameObject("InputManager"); _instance = go.AddComponent(); DontDestroyOnLoad(go); } } return _instance; } } private PlayerInput playerInput; private InputAction touchPressAction; private InputAction touchPositionAction; private ITouchInputConsumer defaultConsumer; private bool isTouchHeld = false; private bool lastFrameInteracted = false; void Awake() { _instance = this; DontDestroyOnLoad(gameObject); playerInput = GetComponent(); if (playerInput == null) { Debug.LogError("[InputManager] InputManager requires a PlayerInput component attached to the same GameObject."); return; } // Find actions by name in the assigned action map touchPressAction = playerInput.actions.FindAction("TouchPress", false); touchPositionAction = playerInput.actions.FindAction("TouchPosition", false); } void OnEnable() { if (touchPressAction != null) { touchPressAction.started += OnTouchPressStarted; touchPressAction.canceled += OnTouchPressCanceled; } if (touchPositionAction != null) touchPositionAction.performed += OnTouchPositionPerformed; } void OnDisable() { if (touchPressAction != null) { touchPressAction.started -= OnTouchPressStarted; touchPressAction.canceled -= OnTouchPressCanceled; } if (touchPositionAction != null) touchPositionAction.performed -= OnTouchPositionPerformed; } public void SetDefaultConsumer(ITouchInputConsumer consumer) { defaultConsumer = consumer; } private void OnTouchPressStarted(InputAction.CallbackContext ctx) { // Touch started (finger down) Vector3 _screenPos = Camera.main.ScreenToWorldPoint(touchPositionAction.ReadValue()); Vector2 screenPos = new Vector2(_screenPos.x, _screenPos.y); lastFrameInteracted = TryDelegateToInteractable(screenPos); if (!lastFrameInteracted) defaultConsumer?.OnTouchPress(screenPos); isTouchHeld = true; } private void OnTouchPressCanceled(InputAction.CallbackContext ctx) { // Touch released (finger up) isTouchHeld = false; // Reset lastFrameInteracted for next frame lastFrameInteracted = false; // Optionally, you can notify consumers of release if needed } private void OnTouchPositionPerformed(InputAction.CallbackContext ctx) { Vector2 pos = ctx.ReadValue(); if (isTouchHeld) { // Convert to world position Vector3 worldPos = Camera.main.ScreenToWorldPoint(pos); Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y); if (!lastFrameInteracted) defaultConsumer?.OnTouchPress(worldPos2D); // Move continuously to finger position } } void Update() { // Continuously advertise the last touch position while held if (isTouchHeld && touchPositionAction != null) { Vector2 pos = touchPositionAction.ReadValue(); Vector3 worldPos = Camera.main.ScreenToWorldPoint(pos); Vector2 worldPos2D = new Vector2(worldPos.x, worldPos.y); if (!lastFrameInteracted) defaultConsumer?.OnTouchPress(worldPos2D); } } private bool TryDelegateToInteractable(Vector2 worldPos) { // Raycast at the world position to find an Interactable Collider2D hit = Physics2D.OverlapPoint(worldPos); if (hit != null) { var interactable = hit.GetComponent(); if (interactable != null) { interactable.OnTouchPress(worldPos); return true; } } return false; } }