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(); } }