gameplay所有基本功能都装了,加入了全局警告。加入飘字等各种东西。
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
@@ -11,6 +11,7 @@ public class NoteSpawner : MonoBehaviour
|
||||
|
||||
public NotePool notePool; // Documentation text normalized.
|
||||
public Transform[] spawnPoints; // Documentation text normalized.
|
||||
public Transform judgmentLine;
|
||||
public GameObject[] notePrefabs; // Documentation text normalized.
|
||||
|
||||
public TextMeshProUGUI globalGameTime;
|
||||
@@ -75,6 +76,7 @@ public class NoteSpawner : MonoBehaviour
|
||||
private Dictionary<int, int> noteIndexToHoldId = new Dictionary<int, int>();
|
||||
|
||||
private const string NoteSpeedPrefKey = "noteSpeedMultiplier";
|
||||
private const float BaseTravelDistance = 10.75f;
|
||||
|
||||
private Coroutine spawnCoroutine;
|
||||
private Coroutine settlementCoroutine;
|
||||
@@ -211,10 +213,13 @@ public class NoteSpawner : MonoBehaviour
|
||||
// Cache parameters that don't change within the loop
|
||||
float sm = Mathf.Clamp(speedMultiplier, SpeedMultiplierMin, SpeedMultiplierMax);
|
||||
float baseTravelTime = (60f / bpm) * 4f;
|
||||
float effectiveTravelTime = baseTravelTime / Mathf.Max(0.0001f, sm);
|
||||
float noteSpeed = CalculateSpeed(effectiveTravelTime);
|
||||
float baseNoteTravelTime = baseTravelTime / Mathf.Max(0.0001f, sm);
|
||||
float noteSpeed = CalculateSpeed(baseNoteTravelTime);
|
||||
float segmentInterval = (60f / bpm) / 4f;
|
||||
|
||||
EnsureJudgmentLine();
|
||||
float[] laneTravelTimes = BuildLaneTravelTimes(noteSpeed);
|
||||
|
||||
// iterate with index so we can map hold notes to generated ids
|
||||
for (int i = 0; i < beatmap.notes.Length; i++)
|
||||
{
|
||||
@@ -223,8 +228,9 @@ public class NoteSpawner : MonoBehaviour
|
||||
yield break;
|
||||
|
||||
NoteData note = beatmap.notes[i];
|
||||
|
||||
float spawnTime = note.time - effectiveTravelTime;
|
||||
|
||||
float travelTime = GetLaneTravelTimeSeconds(laneTravelTimes, note.trackIndex);
|
||||
float spawnTime = note.time - travelTime;
|
||||
float delay = spawnTime - (Time.time - startTime) + spawnOffset;
|
||||
|
||||
if (delay > 0)
|
||||
@@ -241,12 +247,12 @@ public class NoteSpawner : MonoBehaviour
|
||||
if (note.type == "hold")
|
||||
{
|
||||
// create the hold note once and record its id mapping
|
||||
int hid = SpawnHoldNote(note, sm, effectiveTravelTime, noteSpeed, segmentInterval);
|
||||
int hid = SpawnHoldNote(note, sm, travelTime, noteSpeed, segmentInterval);
|
||||
noteIndexToHoldId[i] = hid;
|
||||
}
|
||||
else
|
||||
{
|
||||
SpawnNote(note, sm, effectiveTravelTime, noteSpeed);
|
||||
SpawnNote(note, sm, travelTime, noteSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +274,7 @@ public class NoteSpawner : MonoBehaviour
|
||||
return key;
|
||||
}
|
||||
|
||||
public void SpawnNote(NoteData noteData, float sm, float effectiveTravelTime, float noteSpeed)
|
||||
public void SpawnNote(NoteData noteData, float sm, float travelTime, float noteSpeed)
|
||||
{
|
||||
if (noteData.trackIndex < 0 || noteData.trackIndex >= spawnPoints.Length)
|
||||
{
|
||||
@@ -295,20 +301,8 @@ public class NoteSpawner : MonoBehaviour
|
||||
// Calculate hit time (realtime when note should be judged)
|
||||
float rawHit = startTime + noteData.time + globalHitDelay;
|
||||
float realtimeHit = Mathf.Max(0f, rawHit);
|
||||
|
||||
// Calculate activation time (when note should start moving)
|
||||
float activationTime = realtimeHit - effectiveTravelTime;
|
||||
|
||||
// Compute early compensation for short notes if enabled
|
||||
float noteYOffset = 0f;
|
||||
if (enableYOffsetCompensation)
|
||||
{
|
||||
float timeSinceNoteActivation = Time.time - activationTime;
|
||||
noteYOffset = Mathf.Max(0f, timeSinceNoteActivation * noteSpeed);
|
||||
}
|
||||
|
||||
// Set initial position with offset compensation
|
||||
Vector3 initialPosition = spawnPoint.position + Vector3.down * noteYOffset;
|
||||
|
||||
Vector3 initialPosition = spawnPoint.position;
|
||||
note.transform.position = initialPosition;
|
||||
note.transform.rotation = Quaternion.identity;
|
||||
|
||||
@@ -323,11 +317,11 @@ public class NoteSpawner : MonoBehaviour
|
||||
// Configure controller for absolute positioning (replaces relative Translate)
|
||||
if (noteController != null)
|
||||
{
|
||||
noteController.ConfigureAbsolutePositioning(initialPosition, realtimeHit, effectiveTravelTime, noteYOffset);
|
||||
noteController.ConfigureAbsolutePositioning(initialPosition, realtimeHit, travelTime, 0f);
|
||||
}
|
||||
|
||||
// Schedule calibration for short note to correct any drift
|
||||
StartCoroutine(CalibrateNoteAfterSpawn(noteController, initialPosition));
|
||||
StartCoroutine(CalibrateNoteAfterSpawn(noteController));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -336,7 +330,7 @@ public class NoteSpawner : MonoBehaviour
|
||||
}
|
||||
|
||||
// Modified: return generated holdNoteId so callers can map notes to ids
|
||||
public int SpawnHoldNote(NoteData noteData, float sm, float effectiveTravelTime, float noteSpeed, float segmentInterval)
|
||||
public int SpawnHoldNote(NoteData noteData, float sm, float travelTime, float noteSpeed, float segmentInterval)
|
||||
{
|
||||
if (noteData.trackIndex < 0 || noteData.trackIndex >= spawnPoints.Length)
|
||||
{
|
||||
@@ -388,7 +382,7 @@ public class NoteSpawner : MonoBehaviour
|
||||
if (holdNote != null)
|
||||
{
|
||||
// pass realtime hit time (startTime + note.time) and delay 0, include globalHitDelay
|
||||
holdNote.Setup(holdNoteId, noteData.trackIndex, noteSpeed, baseHit, 0f, false, scheduledEndTime, noteData.color, key, "start", judgeConfig, noteData);
|
||||
holdNote.Setup(holdNoteId, noteData.trackIndex, noteSpeed, baseHit, 0f, false, scheduledEndTime, noteData.color, key, "start", travelTime, judgeConfig, noteData);
|
||||
|
||||
// compute visual scale for hold segments so pieces visually connect across speedMultiplier changes
|
||||
float visualScale = 0.9f * sm + 0.1f; // linear fit: f(1)=1, f(2)=1.9
|
||||
@@ -420,7 +414,7 @@ public class NoteSpawner : MonoBehaviour
|
||||
if (holdSeg != null)
|
||||
{
|
||||
// Documentation text normalized.
|
||||
holdSeg.Setup(holdNoteId, noteData.trackIndex, noteSpeed, baseHit, segmentDelay, false, scheduledEndTime, noteData.color, key, "middle", judgeConfig, noteData);
|
||||
holdSeg.Setup(holdNoteId, noteData.trackIndex, noteSpeed, baseHit, segmentDelay, false, scheduledEndTime, noteData.color, key, "middle", travelTime, judgeConfig, noteData);
|
||||
|
||||
// apply same visual scale so middle pieces visually connect
|
||||
float visualScaleMid = 0.9f * sm + 0.1f;
|
||||
@@ -452,7 +446,7 @@ public class NoteSpawner : MonoBehaviour
|
||||
HoldNote holdEnd = endObj.GetComponent<HoldNote>();
|
||||
if (holdEnd != null)
|
||||
{
|
||||
holdEnd.Setup(holdNoteId, noteData.trackIndex, noteSpeed, baseHit, endDelay, true, scheduledEndTime, noteData.color, key, "end", judgeConfig, noteData);
|
||||
holdEnd.Setup(holdNoteId, noteData.trackIndex, noteSpeed, baseHit, endDelay, true, scheduledEndTime, noteData.color, key, "end", travelTime, judgeConfig, noteData);
|
||||
|
||||
// apply visual scale to end piece as well
|
||||
float visualScaleEnd = 0.9f * sm + 0.1f;
|
||||
@@ -472,6 +466,45 @@ public class NoteSpawner : MonoBehaviour
|
||||
return holdNoteId;
|
||||
}
|
||||
|
||||
private void EnsureJudgmentLine()
|
||||
{
|
||||
if (judgmentLine != null) return;
|
||||
GameObject go = GameObject.FindGameObjectWithTag("JudgmentLine");
|
||||
if (go != null) judgmentLine = go.transform;
|
||||
}
|
||||
|
||||
private float[] BuildLaneTravelTimes(float noteSpeed)
|
||||
{
|
||||
int lanes = spawnPoints != null ? spawnPoints.Length : 0;
|
||||
float[] times = new float[lanes];
|
||||
float safeSpeed = Mathf.Max(0.0001f, noteSpeed);
|
||||
|
||||
for (int i = 0; i < lanes; i++)
|
||||
{
|
||||
float distance = GetLaneDistance(i);
|
||||
times[i] = distance / safeSpeed;
|
||||
}
|
||||
|
||||
return times;
|
||||
}
|
||||
|
||||
private float GetLaneDistance(int trackIndex)
|
||||
{
|
||||
if (spawnPoints == null || trackIndex < 0 || trackIndex >= spawnPoints.Length) return BaseTravelDistance;
|
||||
Transform sp = spawnPoints[trackIndex];
|
||||
if (sp == null) return BaseTravelDistance;
|
||||
if (judgmentLine == null) return BaseTravelDistance;
|
||||
|
||||
return Mathf.Abs(sp.position.y - judgmentLine.position.y);
|
||||
}
|
||||
|
||||
private float GetLaneTravelTimeSeconds(float[] laneTravelTimes, int trackIndex)
|
||||
{
|
||||
if (laneTravelTimes == null || laneTravelTimes.Length == 0) return 0f;
|
||||
if (trackIndex < 0 || trackIndex >= laneTravelTimes.Length) return laneTravelTimes[0];
|
||||
return laneTravelTimes[trackIndex];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Documentation text normalized.
|
||||
[ContextMenu("Force Immediate Settlement")]
|
||||
@@ -578,7 +611,7 @@ public class NoteSpawner : MonoBehaviour
|
||||
|
||||
/// <summary>
|
||||
/// Documentation text normalized.
|
||||
private IEnumerator CalibrateNoteAfterSpawn(NoteController noteController, Vector3 expectedSpawnPos)
|
||||
private IEnumerator CalibrateNoteAfterSpawn(NoteController noteController)
|
||||
{
|
||||
if (noteController == null) yield break;
|
||||
|
||||
@@ -588,13 +621,11 @@ public class NoteSpawner : MonoBehaviour
|
||||
yield return GetCalibrateWait();
|
||||
if (noteObj == null || !noteObj.activeSelf) yield break;
|
||||
|
||||
// Check if note position deviates significantly from expected spawn position
|
||||
float distanceDeviation = Vector3.Distance(noteObj.transform.position, expectedSpawnPos);
|
||||
Vector3 expected = noteController.GetExpectedPosition(Time.time);
|
||||
float distanceDeviation = Vector3.Distance(noteObj.transform.position, expected);
|
||||
if (distanceDeviation > calibrateTolerance)
|
||||
{
|
||||
// Snap to expected position while allowing vertical movement
|
||||
Vector3 correctedPos = expectedSpawnPos;
|
||||
noteObj.transform.position = correctedPos;
|
||||
noteObj.transform.position = expected;
|
||||
if (JudgeManager.IsDebugEnabled) Debug.Log($"[NoteSpawner] Calibrated short note position, deviation was {distanceDeviation:F4}");
|
||||
}
|
||||
}
|
||||
@@ -612,7 +643,7 @@ public class NoteSpawner : MonoBehaviour
|
||||
|
||||
private float CalculateSpeed(float noteTravelTime)
|
||||
{
|
||||
return 10.75f / noteTravelTime;
|
||||
return BaseTravelDistance / noteTravelTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user