备份,准备做双端

This commit is contained in:
2026-07-30 23:15:58 +08:00
parent add675e45d
commit ec4ec53545
88 changed files with 4050 additions and 872 deletions
@@ -10,9 +10,17 @@ using UnityEngine.UI;
public class InputManager : MonoBehaviour
{
public static InputManager Instance { get; private set; }
// Legacy KeyCode-based events (maintained for backward compatibility with existing Note/HoldNote code).
// These are now fired by OnTrackInput handlers after receiving dspTime from GameplayInputActions.
public static event Action<KeyCode> OnKeyPressed;
public static event Action<KeyCode> OnKeyReleased;
// New dspTime-carrying events: track index + dspTime at the moment Input System captured the event.
// Allows sub-frame-accurate judgement by converting dspTime → song time via GameplayClock.SongTimeFromDsp.
public static event Action<int, double> OnTrackPressedWithDspTime;
public static event Action<int, double> OnTrackReleasedWithDspTime;
private static readonly string[] TrackColors = { "red", "green", "yellow", "purple", "blue" };
[Header("Inspector")]
@@ -82,6 +90,48 @@ public class InputManager : MonoBehaviour
if (t != null) t.color = keyInactiveColor;
}
}
// Ensure GameplayInputActions exists (auto-create if missing).
if (GameplayInputActions.Instance == null)
{
GameObject inputActionsGo = new GameObject("GameplayInputActions");
inputActionsGo.AddComponent<GameplayInputActions>();
DontDestroyOnLoad(inputActionsGo);
}
// Subscribe to Input System events from GameplayInputActions (dspTime-carrying press/release).
GameplayInputActions.OnTrackPressed += OnTrackInput_Press;
GameplayInputActions.OnTrackReleased += OnTrackInput_Release;
}
private void OnDestroy()
{
if (GameplayInputActions.Instance != null)
{
GameplayInputActions.OnTrackPressed -= OnTrackInput_Press;
GameplayInputActions.OnTrackReleased -= OnTrackInput_Release;
}
}
/// <summary>
/// Handle track press from GameplayInputActions (Input System). Updates held state,
/// fires both legacy KeyCode event and new dspTime event, and updates visuals.
/// </summary>
private void OnTrackInput_Press(int trackIndex, double pressDspTime)
{
if (IsBlockedByPause()) return;
KeyCode sourceKey = trackIndex >= 0 && trackIndex < cachedKeys.Length ? cachedKeys[trackIndex] : KeyCode.None;
PressTrack(trackIndex, sourceKey, pressDspTime);
}
/// <summary>
/// Handle track release from GameplayInputActions (Input System). Updates held state,
/// fires both legacy KeyCode event and new dspTime event, and updates visuals.
/// </summary>
private void OnTrackInput_Release(int trackIndex, double releaseDspTime)
{
if (IsBlockedByPause()) return;
ReleaseTrack(trackIndex, releaseDspTime);
}
private void RefreshKeyCache()
@@ -129,24 +179,9 @@ public class InputManager : MonoBehaviour
}
pauseBlockedLastFrame = false;
for (int i = 0; i < TrackColors.Length; i++)
{
KeyCode key = cachedKeys[i];
if (key == KeyCode.None) continue;
if (Input.GetKeyDown(key))
PressTrack(i);
if (Input.GetKeyUp(key))
ReleaseTrack(i);
}
if (cachedSecondaryTrack3Key != KeyCode.None)
{
if (Input.GetKeyDown(cachedSecondaryTrack3Key))
PressTrack(2, cachedSecondaryTrack3Key);
if (Input.GetKeyUp(cachedSecondaryTrack3Key))
ReleaseTrack(2);
}
// Legacy Input.GetKeyDown polling removed: keyboard input now comes from
// GameplayInputActions (Input System) via OnTrackInput_Press/Release handlers.
// Touch input still drives PressTrack/ReleaseTrack directly via TrackTouchInput.
}
/// <summary>
@@ -158,19 +193,27 @@ public class InputManager : MonoBehaviour
public void PressTrack(int index)
{
KeyCode sourceKey = index >= 0 && index < cachedKeys.Length ? cachedKeys[index] : KeyCode.None;
PressTrack(index, sourceKey);
// Touch/other callers without an event timestamp use the current dspTime.
PressTrack(index, sourceKey, AudioSettings.dspTime);
}
public void PressTrack(int index, KeyCode sourceKey)
{
PressTrack(index, sourceKey, AudioSettings.dspTime);
}
public void PressTrack(int index, KeyCode sourceKey, double pressDspTime)
{
if (index < 0 || index >= TrackColors.Length) return;
bool wasHeld = trackHeldCount[index] > 0;
trackHeldCount[index]++;
// Always fire tap judgment pulse, even if already held (fixes rapid same-track taps)
// Always fire tap judgment pulse, even if already held (fixes rapid same-track taps).
// Fire both the legacy KeyCode event and the new dspTime event so both consumers work.
KeyCode key = cachedKeys[index];
if (key != KeyCode.None)
OnKeyPressed?.Invoke(key);
OnTrackPressedWithDspTime?.Invoke(index, pressDspTime);
if (trackKeyTexts != null && index < trackKeyTexts.Length)
{
@@ -201,6 +244,11 @@ public class InputManager : MonoBehaviour
/// on pointer-up. Clears the held-state table, raises OnKeyReleased, and resets visuals.
/// </summary>
public void ReleaseTrack(int index)
{
ReleaseTrack(index, AudioSettings.dspTime);
}
public void ReleaseTrack(int index, double releaseDspTime)
{
if (index < 0 || index >= TrackColors.Length) return;
if (trackHeldCount[index] <= 0) return; // not held; nothing to release
@@ -211,6 +259,7 @@ public class InputManager : MonoBehaviour
KeyCode key = cachedKeys[index];
if (key != KeyCode.None)
OnKeyReleased?.Invoke(key);
OnTrackReleasedWithDspTime?.Invoke(index, releaseDspTime);
if (laneSprites != null && index < laneSprites.Length)
SetSpriteAlpha(laneSprites[index], 0f);