61 lines
2.1 KiB
C#
61 lines
2.1 KiB
C#
using System;
|
||
|
||
/// <summary>
|
||
/// FAST/SLOW 早晚反馈预埋接口。
|
||
///
|
||
/// 判定命中时(非 Miss)由判定逻辑广播一次带符号的时间偏移,供 UI 层显示"早/晚"提示、
|
||
/// 或供校准/统计模块消费。默认无任何订阅者时为 no-op,不产生任何行为、不影响判定与计分。
|
||
///
|
||
/// 约定(与 osu 系惯例一致):
|
||
/// signedOffsetMs = (pressTime - hitTime) * 1000
|
||
/// > 0 → 按晚了(SLOW / Late)
|
||
/// < 0 → 按早了(FAST / Early)
|
||
/// = 0 → 正中
|
||
///
|
||
/// 纯附加接口:不改变任何现有判定/计分业务逻辑。接入方只需订阅 OnJudgeOffset。
|
||
/// </summary>
|
||
public static class JudgeFeedback
|
||
{
|
||
public enum Timing
|
||
{
|
||
Exact,
|
||
Fast, // 偏早
|
||
Slow // 偏晚
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判定偏移事件。参数:(trackIndex, judgeResult, signedOffsetMs, timing)。
|
||
/// 仅在命中档(Perfect/Great/Good)判定成功时触发;Miss 不触发(无有效偏移)。
|
||
/// </summary>
|
||
public static event Action<int, string, float, Timing> OnJudgeOffset;
|
||
|
||
/// <summary>
|
||
/// 将带符号偏移归类为 Fast/Slow/Exact。deadZoneMs 内视为正中(默认 0,即严格按符号)。
|
||
/// </summary>
|
||
public static Timing Classify(float signedOffsetMs, float deadZoneMs = 0f)
|
||
{
|
||
if (signedOffsetMs > deadZoneMs) return Timing.Slow;
|
||
if (signedOffsetMs < -deadZoneMs) return Timing.Fast;
|
||
return Timing.Exact;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 由判定逻辑调用,广播一次早晚反馈。无订阅者时为 no-op。
|
||
/// 内部吞掉订阅者异常,保证反馈通道永不影响判定主流程。
|
||
/// </summary>
|
||
public static void Report(int trackIndex, string judgeResult, float signedOffsetMs)
|
||
{
|
||
var handler = OnJudgeOffset;
|
||
if (handler == null) return; // 预埋:默认无接入,零开销、零副作用。
|
||
|
||
try
|
||
{
|
||
handler.Invoke(trackIndex, judgeResult, signedOffsetMs, Classify(signedOffsetMs));
|
||
}
|
||
catch
|
||
{
|
||
// 反馈通道故障绝不能影响判定/计分。
|
||
}
|
||
}
|
||
}
|