Files
2026-07-25 08:31:10 +08:00

81 lines
2.6 KiB
C#

using UnityEngine;
using UnityEngine.EventSystems;
/// <summary>
/// Touch/click region that drives one gameplay track (0-4) through InputManager,
/// exactly as if the bound keyboard key were pressed/released. Attach to a UI
/// element (Image with Raycast Target on) laid over a lane; set trackIndex in the
/// inspector. Uses EventSystem pointer callbacks so it supports multi-touch (each
/// finger routes its own down/up to the region it started on) and works on Android
/// touch as well as desktop mouse.
///
/// Judgment/scoring is unchanged: this only injects the same press/release the
/// keyboard path produces. On a track already held by keyboard, PressTrack/
/// ReleaseTrack are idempotent so there is no double-trigger.
/// </summary>
[RequireComponent(typeof(RectTransform))]
public class TrackTouchRegion : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
[Tooltip("Track this region controls: 0=red 1=green 2=yellow 3=purple 4=blue")]
[Range(0, 4)]
public int trackIndex = 0;
// The pointerId that pressed this region, so we only release on the matching
// pointer's up event (relevant for multi-touch where several fingers are down).
private int activePointerId = int.MinValue;
private bool pressed = false;
private static bool ShouldProcessTouchInput()
{
#if UNITY_ANDROID || UNITY_IOS
return true;
#else
return false;
#endif
}
private void Awake()
{
if (!ShouldProcessTouchInput())
enabled = false;
}
public void OnPointerDown(PointerEventData eventData)
{
if (!ShouldProcessTouchInput()) return;
if (pressed) return; // already driven by another finger; ignore extras
var im = InputManager.Instance;
if (im == null) return;
activePointerId = eventData.pointerId;
pressed = true;
im.PressTrack(trackIndex);
}
public void OnPointerUp(PointerEventData eventData)
{
if (!ShouldProcessTouchInput()) return;
if (!pressed || eventData.pointerId != activePointerId) return;
var im = InputManager.Instance;
pressed = false;
activePointerId = int.MinValue;
if (im != null) im.ReleaseTrack(trackIndex);
}
private void OnDisable()
{
if (!ShouldProcessTouchInput()) return;
// If the region is hidden/destroyed mid-hold, make sure the track is released
// so a note is not left stuck in the held state.
if (pressed)
{
pressed = false;
activePointerId = int.MinValue;
var im = InputManager.Instance;
if (im != null) im.ReleaseTrack(trackIndex);
}
}
}