Files
bansonic_beta_main/Assets/scripts/gamePlay_gameplay/ChartModifiers.cs
T
2026-07-30 23:15:58 +08:00

127 lines
3.9 KiB
C#

using UnityEngine;
/// <summary>
/// 谱面修饰符:Mirror(镜像)/ Random(随机打乱轨道)。
/// 纯视觉重映射 trackIndex,对判定/计分完全等效(业务逻辑不变)。
/// PlayerPrefs 持久化,默认全部关闭。
/// </summary>
public static class ChartModifiers
{
private const string PREF_MIRROR = "ChartModifier_Mirror";
private const string PREF_RANDOM = "ChartModifier_Random";
// 当前会话的映射表缓存(Random 需要在谱面加载时固定一次,整局不变)。
private static int[] cachedMapping = null;
private static bool cachedMappingDirty = true;
/// <summary>
/// Mirror 开关(默认 false)。镜像 5 轨:0↔4, 1↔3, 2 不变。
/// </summary>
public static bool MirrorEnabled
{
get => PlayerPrefs.GetInt(PREF_MIRROR, 0) == 1;
set
{
PlayerPrefs.SetInt(PREF_MIRROR, value ? 1 : 0);
PlayerPrefs.Save();
cachedMappingDirty = true;
}
}
/// <summary>
/// Random 开关(默认 false)。将 5 轨随机打乱(每次加载谱面时重新洗牌一次)。
/// </summary>
public static bool RandomEnabled
{
get => PlayerPrefs.GetInt(PREF_RANDOM, 0) == 1;
set
{
PlayerPrefs.SetInt(PREF_RANDOM, value ? 1 : 0);
PlayerPrefs.Save();
cachedMappingDirty = true;
}
}
/// <summary>
/// 标记映射表需要重建(谱面重新加载时调用)。
/// </summary>
public static void InvalidateMapping()
{
cachedMappingDirty = true;
}
/// <summary>
/// 获取当前生效的 trackIndex 映射表。输入原始 trackIndex,返回重映射后的 trackIndex。
/// 优先级:Random > Mirror > 原值。Random 会在首次调用时固定洗牌结果(整局不变)。
/// </summary>
public static int RemapTrackIndex(int originalIndex)
{
if (originalIndex < 0 || originalIndex >= 5) return originalIndex;
if (!MirrorEnabled && !RandomEnabled) return originalIndex;
if (cachedMappingDirty)
{
RebuildMapping();
cachedMappingDirty = false;
}
return cachedMapping[originalIndex];
}
private static void RebuildMapping()
{
if (cachedMapping == null || cachedMapping.Length != 5)
cachedMapping = new int[5];
// 初始为恒等映射
for (int i = 0; i < 5; i++) cachedMapping[i] = i;
// Random 优先(若开启则整体洗牌,覆盖 Mirror)
if (RandomEnabled)
{
// Fisher-Yates shuffle
System.Random rng = new System.Random();
for (int i = 4; i > 0; i--)
{
int j = rng.Next(i + 1);
int temp = cachedMapping[i];
cachedMapping[i] = cachedMapping[j];
cachedMapping[j] = temp;
}
}
// Mirror(仅在 Random 关闭时生效)
else if (MirrorEnabled)
{
cachedMapping[0] = 4;
cachedMapping[1] = 3;
cachedMapping[2] = 2; // 中轨不变
cachedMapping[3] = 1;
cachedMapping[4] = 0;
}
}
/// <summary>
/// 反向映射:输入重映射后的 trackIndex,返回原始 trackIndex(用于输入事件还原)。
/// 当前项目输入事件已经按 trackIndex 匹配,通常无需反向映射。
/// </summary>
public static int UnmapTrackIndex(int remappedIndex)
{
if (remappedIndex < 0 || remappedIndex >= 5) return remappedIndex;
if (!MirrorEnabled && !RandomEnabled) return remappedIndex;
if (cachedMappingDirty)
{
RebuildMapping();
cachedMappingDirty = false;
}
for (int i = 0; i < 5; i++)
{
if (cachedMapping[i] == remappedIndex) return i;
}
return remappedIndex;
}
}