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