175 lines
5.1 KiB
C#
175 lines
5.1 KiB
C#
using UnityEngine;
|
||
using EasyChart;
|
||
using System.Collections.Generic;
|
||
|
||
/// <summary>
|
||
/// 判定偏移直方图:用 EasyChart 可视化判定偏移分布。
|
||
/// 从 ScoreManager.OffsetSamples 读取数据并绘制直方图。
|
||
/// 供后续快速接入(需你指定在何处显示此组件)。
|
||
/// </summary>
|
||
[RequireComponent(typeof(ChartElement))]
|
||
public class JudgeOffsetHistogram : MonoBehaviour
|
||
{
|
||
[Header("数据源")]
|
||
[SerializeField] private ScoreManager scoreManager;
|
||
|
||
[Header("直方图配置")]
|
||
[SerializeField] private int binCount = 20; // 分箱数(横轴分段)
|
||
[SerializeField] private float rangeMin = -200f; // ms
|
||
[SerializeField] private float rangeMax = 200f; // ms
|
||
[SerializeField] private Color barColor = new Color(0.2f, 0.6f, 1f, 0.8f);
|
||
|
||
[Header("标签")]
|
||
[SerializeField] private string chartTitle = "Judge Offset Distribution";
|
||
[SerializeField] private string xAxisLabel = "Offset (ms)";
|
||
[SerializeField] private string yAxisLabel = "Count";
|
||
|
||
private ChartElement chartElement;
|
||
private ChartData chartData;
|
||
|
||
private void Awake()
|
||
{
|
||
chartElement = GetComponent<ChartElement>();
|
||
if (chartElement == null)
|
||
{
|
||
Debug.LogError("[JudgeOffsetHistogram] ChartElement component not found!");
|
||
return;
|
||
}
|
||
|
||
// 自动查找 ScoreManager(如果未手动赋值)
|
||
if (scoreManager == null)
|
||
{
|
||
scoreManager = FindObjectOfType<ScoreManager>();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 刷新直方图:从 ScoreManager.offsetSamples 读取数据并绘制。
|
||
/// 在结算页显示时调用。
|
||
/// </summary>
|
||
public void RefreshHistogram()
|
||
{
|
||
if (scoreManager == null)
|
||
{
|
||
Debug.LogWarning("[JudgeOffsetHistogram] ScoreManager not assigned.");
|
||
return;
|
||
}
|
||
|
||
// 读取偏移样本(ms)
|
||
IReadOnlyList<float> samples = scoreManager.OffsetSamples;
|
||
if (samples == null || samples.Count == 0)
|
||
{
|
||
Debug.LogWarning("[JudgeOffsetHistogram] No offset samples available.");
|
||
return;
|
||
}
|
||
|
||
// 分箱统计
|
||
int[] bins = new int[binCount];
|
||
float binWidth = (rangeMax - rangeMin) / binCount;
|
||
|
||
foreach (float offset in samples)
|
||
{
|
||
if (offset < rangeMin || offset >= rangeMax) continue; // 超出范围忽略
|
||
|
||
int binIndex = Mathf.FloorToInt((offset - rangeMin) / binWidth);
|
||
binIndex = Mathf.Clamp(binIndex, 0, binCount - 1);
|
||
bins[binIndex]++;
|
||
}
|
||
|
||
// 构建 EasyChart ChartData
|
||
BuildChartData(bins, binWidth);
|
||
|
||
// 应用到 ChartElement
|
||
if (chartElement != null && chartData != null)
|
||
{
|
||
chartElement.SetData(chartData);
|
||
Debug.Log($"[JudgeOffsetHistogram] Refreshed with {samples.Count} samples, {binCount} bins.");
|
||
}
|
||
}
|
||
|
||
private void BuildChartData(int[] bins, float binWidth)
|
||
{
|
||
chartData = new ChartData();
|
||
|
||
// 配置坐标系为笛卡尔2D
|
||
chartData.CoordinateSystem = CoordinateSystemType.Cartesian2D;
|
||
chartData.XAxisId = AxisId.XBottom;
|
||
chartData.YAxisId = AxisId.YLeft;
|
||
|
||
// X 轴配置(类目轴,显示偏移区间)
|
||
var xAxis = new AxisConfig
|
||
{
|
||
id = AxisId.XBottom,
|
||
axisType = AxisType.Category,
|
||
labels = new List<string>()
|
||
};
|
||
for (int i = 0; i < binCount; i++)
|
||
{
|
||
float binCenter = rangeMin + (i + 0.5f) * binWidth;
|
||
xAxis.labels.Add($"{binCenter:F0}");
|
||
}
|
||
|
||
// Y 轴配置(数值轴,显示计数)
|
||
var yAxis = new AxisConfig
|
||
{
|
||
id = AxisId.YLeft,
|
||
axisType = AxisType.Value,
|
||
minValue = 0f,
|
||
autoRangeMin = true,
|
||
autoRangeMax = true
|
||
};
|
||
|
||
chartData.Axes = new List<AxisConfig> { xAxis, yAxis };
|
||
|
||
// 创建柱状图系列
|
||
var serie = new Serie
|
||
{
|
||
name = chartTitle,
|
||
type = SerieType.Bar,
|
||
seriesData = new List<SeriesData>()
|
||
};
|
||
|
||
// 填充数据点
|
||
for (int i = 0; i < binCount; i++)
|
||
{
|
||
serie.seriesData.Add(new SeriesData
|
||
{
|
||
x = i,
|
||
value = bins[i]
|
||
});
|
||
}
|
||
|
||
// 配置柱状图样式(可选)
|
||
var barSettings = new BarSettings();
|
||
if (barSettings.textureFill == null)
|
||
{
|
||
barSettings.textureFill = new TextureFillSettings { color = barColor };
|
||
}
|
||
else
|
||
{
|
||
barSettings.textureFill.color = barColor;
|
||
}
|
||
serie.settings = barSettings;
|
||
|
||
chartData.Series = new List<Serie> { serie };
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清空直方图。
|
||
/// </summary>
|
||
public void ClearHistogram()
|
||
{
|
||
if (chartElement != null)
|
||
{
|
||
chartElement.SetData(null);
|
||
}
|
||
}
|
||
|
||
// 供 Inspector 测试用的按钮方法
|
||
[ContextMenu("Test Refresh Histogram")]
|
||
private void TestRefresh()
|
||
{
|
||
RefreshHistogram();
|
||
}
|
||
}
|