using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; namespace Kill.UI.Components { /// /// 雷达热力图组件 /// 在雷达图图片上根据角度(0-180度)和距离数据显示热力点 /// 角度定义:左侧0度,正上方90度,右侧180度 /// public class RadarHeatmap : MonoBehaviour { [Header("雷达图背景")] [Tooltip("雷达图背景图片")] public Image radarBackground; [Tooltip("雷达图半径(从中心到边缘的距离)")] public float radius = 200f; [Header("热力点预设")] [Tooltip("热力点预制体")] public GameObject heatPointPrefab; // 数据点列表 private List dataPoints = new List(); // 热力点对象池 private List heatPointPool = new List(); // 容器 public RectTransform heatPointContainer; /// /// 热力图数据点 /// [Serializable] public class HeatmapData { [Tooltip("角度 (0-180度,左侧为0度,正上方为90度,右侧为180度)")] [Range(0f, 180f)] public float angle; [Tooltip("距离 (0-1,相对于雷达半径的比例)")] [Range(0f, 1f)] public float distance; [Tooltip("自定义数据")] public object customData; public HeatmapData(float angle, float distance, object customData = null) { this.angle = Mathf.Clamp(angle, 0f, 180f); this.distance = Mathf.Clamp01(distance); this.customData = customData; } } private void Awake() { InitializeContainer(); } /// /// 初始化容器 /// private void InitializeContainer() { // 如果没有指定背景图片,尝试获取自身的Image if (radarBackground == null) { radarBackground = GetComponent(); } } /// /// 设置数据并刷新热力图 /// public void SetData(List data) { dataPoints = data ?? new List(); RefreshHeatmap(); } /// /// 添加单个数据点 /// public void AddDataPoint(HeatmapData data) { dataPoints.Add(data); CreateHeatPoint(data); } /// /// 清除所有数据 /// public void ClearData() { dataPoints.Clear(); RefreshHeatmap(); } /// /// 刷新热力图显示 /// private void RefreshHeatmap() { // 回收所有热力点 foreach (var point in heatPointPool) { if (point != null) { point.SetActive(false); } } // 创建新的热力点 for (int i = 0; i < dataPoints.Count; i++) { if (i < heatPointPool.Count) { UpdateHeatPoint(heatPointPool[i], dataPoints[i]); } else { CreateHeatPoint(dataPoints[i]); } } } /// /// 创建热力点 /// private void CreateHeatPoint(HeatmapData data) { if (heatPointPrefab == null) { Debug.LogError("[RadarHeatmap] 热力点预制体未设置!"); return; } GameObject pointObj = Instantiate(heatPointPrefab, heatPointContainer); RectTransform rect = pointObj.GetComponent(); // 计算位置 Vector2 position = CalculatePosition(data.angle, data.distance); rect.anchoredPosition = position; heatPointPool.Add(pointObj); } /// /// 更新热力点 /// private void UpdateHeatPoint(GameObject pointObj, HeatmapData data) { if (pointObj == null) return; pointObj.SetActive(true); RectTransform rect = pointObj.GetComponent(); // 更新位置 Vector2 position = CalculatePosition(data.angle, data.distance); rect.anchoredPosition = position; } /// /// 计算数据点在雷达图上的位置 /// 角度定义:左侧0度,正上方90度,右侧180度 /// private Vector2 CalculatePosition(float angle, float distance) { // 将角度转换为弧度 // 左侧0度 -> 180度,正上方90度 -> 90度 // 转换为标准极坐标:0度为正右方,逆时针增加 // 所以:左侧0度 = 180度,正上方90度 = 90度,右侧180度 = 0度 float standardAngle = 180f - angle; float radian = standardAngle * Mathf.Deg2Rad; // 计算实际距离 float actualDistance = distance * radius; // 计算坐标 float x = Mathf.Cos(radian) * actualDistance; float y = Mathf.Sin(radian) * actualDistance; return new Vector2(x, y); } /// /// 设置雷达图半径 /// public void SetRadius(float newRadius) { radius = newRadius; RefreshHeatmap(); } /// /// 获取数据点数量 /// public int GetDataPointCount() { return dataPoints.Count; } /// /// 获取指定索引的数据点 /// public HeatmapData GetDataPoint(int index) { if (index >= 0 && index < dataPoints.Count) { return dataPoints[index]; } return null; } } }