RadarChart.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class RadarChart : Image
{
[SerializeField]
private int pointCount;
[SerializeField]
private List<RectTransform> pointList;
[SerializeField]
private Sprite pointSprite;
[SerializeField]
private Color pointColor=Color.white;
[SerializeField]
private Vector2 pointSize;
[SerializeField]
private List<RaderChartHandler> handlerList;
[SerializeField]
private float[] handlerRadio;//代表每个handler所占那条轴线的比例
private void Update()
{
//设置成dirty状态,此状态下顶点信息会实时刷新,实时重新连接绘制
SetVerticesDirty();
}
//图形界面编写
protected override void OnPopulateMesh(VertexHelper vh)
{
vh.Clear();
//AddVerts(vh);
AddVertsTemplete(vh);
AddTriangle(vh);
}
//把handler作为顶点信息添加进去
private void AddVerts(VertexHelper vh)
{
foreach (RaderChartHandler hander in handlerList)
{
vh.AddVert(hander.transform.localPosition,color,Vector2.zero);
}
}
//当要添加进去的精灵不是五边形,是矩形时候,计算uv坐标,把矩形上边拉伸,成五边形
private void AddVertsTemplete(VertexHelper vh)
{
vh.AddVert(handlerList[0].transform.localPosition, color, new Vector2(0.5f,1));
vh.AddVert(handlerList[1].transform.localPosition, color, new Vector2(0, 1));
vh.AddVert(handlerList[2].transform.localPosition, color, new Vector2(0, 0));
vh.AddVert(handlerList[3].transform.localPosition, color, new Vector2(1, 0));
vh.AddVert(handlerList[4].transform.localPosition, color, new Vector2(1, 1));
}
//根据顶点信息生成三角形
private void AddTriangle(VertexHelper vh)
{
for (int i = 1; i < pointCount-1; i++)
{
vh.AddTriangle(0, i + 1, i);
}
}
//初始化
public void InitPoint()
{
ClearPoints();
pointList = new List<RectTransform>();
SpawnPoint();
SetPointPos();
}
//清除point
private void ClearPoints()
{
if (pointList==null)
{
return;
}
foreach (RectTransform point in pointList)
{
if (point!=null)
{
//立即销毁对象,该函数应只在编写 Editor 代码时使用,因为在编辑模式下,永远不会调用延迟销毁(destory)。
//RectTransform 是一个组件,它可以直接被销毁,而 Unity 会自动处理与之关联的游戏对象。
//因此,直接调用 DestroyImmediate(point) 就足够了,因为它会处理 RectTransform 所在的游戏对象。
DestroyImmediate(point);
}
}
}
//设置几个point点的初始位置
private void SetPointPos()
{
//根据弧度求出point的坐标
float radian = 2 * Mathf.PI / pointCount;
float radius = 100;
float curRadian = Mathf.PI * 0.5f;
for (int i = 0; i < pointCount; i++)
{
float x = Mathf.Cos(curRadian) * radius;
float y = Mathf.Sin(curRadian) * radius;
curRadian += radian;
//设置锚定位置,此 RectTransform 的轴心相对于锚点参考点的位置。
pointList[i].anchoredPosition = new Vector2(x, y);
}
}
//设置出生点数
private void SpawnPoint()
{
for (int i = 0; i < pointCount; i++)
{
GameObject point = new GameObject("Point" + i);
point.transform.parent = transform;
pointList.Add(point.AddComponent<RectTransform>());
}
}
//初始化中间可操作点
public void InitHandlers()
{
ClearHandlers();
handlerList = new List<RaderChartHandler>();
SpawnHandlers();
SetHandlerPos();
}
private void ClearHandlers()
{
if (handlerList == null)
{
return;
}
foreach (RaderChartHandler handler in handlerList)
{
if (handler != null)
{
//立即销毁对象,该函数应只在编写 Editor 代码时使用,因为在编辑模式下,永远不会调用延迟销毁(destory)。
//DestroyImmediate(handler.gameObject) 需要指定 gameObject 是因为 RaderChartHandler 是一个脚本组件,
//而 DestroyImmediate 只能销毁游戏对象或其组件。
DestroyImmediate(handler.gameObject);
}
}
}
private void SpawnHandlers()
{
//创建一个缓存变量
RaderChartHandler handler = null;
for (int i = 0; i < pointCount; i++)
{
GameObject point = new GameObject("Handler" + i);
point.AddComponent<RectTransform>();
point.AddComponent<Image>();
//使用缓存变量存储handlerpoint的一个radercharthandler组件
handler=point.AddComponent<RaderChartHandler>();
handler.SetParent(transform);
handler.ChangeSprite(pointSprite);
handler.ChangeColor(pointColor);
handler.SetSize(pointSize);
handlerList.Add(handler);
}
}
private void SetHandlerPos()
{
if (handlerRadio == null||handlerRadio.Length<pointCount)
{
for (int i = 0;i < pointCount;i++)
{
handlerList[i].SetPos(pointList[i].anchoredPosition);
}
}
else
{
for (int i = 0;i<pointCount;i++)
{
handlerList[i].SetPos(pointList[i].anchoredPosition * handlerRadio[i]);
}
}
}
}
RadarChartHandler.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class RaderChartHandler : MonoBehaviour, IDragHandler
{
//获得image组件属性,利用属性来设置方法
private Image _image;
private Image image
{
get
{
if (_image == null)
{
_image = GetComponent<Image>();
}
return _image;
}
}
//获得recttransform组件属性,利用属性来设置方法
private RectTransform _rect;
private RectTransform rect
{
get
{
if (_rect == null)
{
_rect = GetComponent<RectTransform>();
}
return _rect;
}
}
public void SetParent(Transform parent)
{
transform.SetParent(parent);
}
public void ChangeSprite(Sprite sprite)
{
image.sprite = sprite;
}
public void ChangeColor(Color color)
{
image.color = color;
}
public void SetSize(Vector2 size)
{
rect.sizeDelta = size;
}
public void SetPos(Vector2 pos)
{
rect.anchoredPosition = pos;
}
public void OnDrag(PointerEventData eventData)
{
rect.anchoredPosition += eventData.delta/GetScale();
}
private float GetScale()
{
return rect.lossyScale.x;
}
}
RadarChartEditor.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(RadarChart), true)]
[CanEditMultipleObjects]
public class RadarChartEditor : UnityEditor.UI.ImageEditor
{
SerializedProperty pointCount;
SerializedProperty pointSprite;
SerializedProperty pointColor;
SerializedProperty pointSize;
SerializedProperty handlerRadio;
protected override void OnEnable()
{
base.OnEnable();
pointCount = serializedObject.FindProperty("pointCount");
pointSprite = serializedObject.FindProperty("pointSprite");
pointColor = serializedObject.FindProperty("pointColor");
pointSize = serializedObject.FindProperty("pointSize");
handlerRadio = serializedObject.FindProperty("handlerRadio");
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
EditorGUILayout.PropertyField(pointCount);
EditorGUILayout.PropertyField(pointSprite);
EditorGUILayout.PropertyField(pointColor);
EditorGUILayout.PropertyField(pointSize);
EditorGUILayout.PropertyField(handlerRadio,true);
RadarChart radar = target as RadarChart;
if (radar != null)
{
if (GUILayout.Button("生成雷达图顶点"))
{
radar.InitPoint();
}
if (GUILayout.Button("生成内部可操作顶点"))
{
radar.InitHandlers();
}
}
serializedObject.ApplyModifiedProperties();
if (GUI.changed)
{
EditorUtility.SetDirty(target);
}
}
}