using UnityEngine;
using EasyChart;
using System.Collections.Generic;
///
/// 判定偏移直方图:用 EasyChart 可视化判定偏移分布。
/// 从 ScoreManager.OffsetSamples 读取数据并绘制直方图。
/// 供后续快速接入(需你指定在何处显示此组件)。
///
[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();
if (chartElement == null)
{
Debug.LogError("[JudgeOffsetHistogram] ChartElement component not found!");
return;
}
// 自动查找 ScoreManager(如果未手动赋值)
if (scoreManager == null)
{
scoreManager = FindObjectOfType();
}
}
///
/// 刷新直方图:从 ScoreManager.offsetSamples 读取数据并绘制。
/// 在结算页显示时调用。
///
public void RefreshHistogram()
{
if (scoreManager == null)
{
Debug.LogWarning("[JudgeOffsetHistogram] ScoreManager not assigned.");
return;
}
// 读取偏移样本(ms)
IReadOnlyList 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()
};
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 { xAxis, yAxis };
// 创建柱状图系列
var serie = new Serie
{
name = chartTitle,
type = SerieType.Bar,
seriesData = new List()
};
// 填充数据点
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 };
}
///
/// 清空直方图。
///
public void ClearHistogram()
{
if (chartElement != null)
{
chartElement.SetData(null);
}
}
// 供 Inspector 测试用的按钮方法
[ContextMenu("Test Refresh Histogram")]
private void TestRefresh()
{
RefreshHistogram();
}
}