效果大致如下:

代碼如下:
using System.Collections;
using System.Collections.Generic;
using System.Linq;//.Max()屬于該命名空間
using UnityEngine;
using UnityEngine.UI;
//繼承繪制
public class RadarChart : Graphic
{
public Texture texture;//背景圖
public float[] arr;
public Color backColor;
public float padding = 0;//邊距
public float thick = 1;//描邊的粗細
public Color sideColor;//描邊的顏色
public float[] arr2;
public Color arr2Color;
public Color side2Color;//描邊的顏色
//重新繪制,每次改變數(shù)組中數(shù)值后調(diào)用
public override void SetVerticesDirty()
{
base.SetVerticesDirty();
}
//重新圖片讀取
public override Texture mainTexture {
get
{
if (texture == null)
{
if (material != null && material.mainTexture != null)
{
return material.mainTexture;
}
return s_WhiteTexture;
}
return texture;
}
}
protected override void OnPopulateMesh(VertexHelper vh)
{
//清理網(wǎng)格
vh.Clear();
//獲取ui的大小,相當于rectTransform.rect
Rect rect = GetPixelAdjustedRect();
//繪制背景圖
Vector4 v = new Vector4(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
vh.AddVert(new Vector3(v.x, v.y), backColor, new Vector2(0f, 0.15f));
vh.AddVert(new Vector3(v.x, v.w), backColor, new Vector2(0f, 0.9f));
vh.AddVert(new Vector3(v.z, v.w), backColor, new Vector2(1f, 0.9f));
vh.AddVert(new Vector3(v.z, v.y), backColor, new Vector2(1f, 0.15f));
vh.AddTriangle(0, 1, 2);
vh.AddTriangle(2, 3, 0);
//計算半徑最大值
//半徑的最大值 = 變寬最小值的一半
float rMax;
if (rect.width < rect.height)
{
rMax = (rect.width - padding) / 2;
}
else
{
rMax = (rect.height - padding) / 2;
}
//計算半徑與傳入的最大值的比值
float per = rMax / arr.Max();
//計算每個角的弧度
float ang = Mathf.PI * 2 / arr.Length;
//添加圓心頂點
vh.AddVert(new Vector3(0, 0, 0), color, Vector4.zero);
for (int i = 0; i < arr.Length; i++)
{
float x = Mathf.Sin(ang * i) * arr[i] * per;
float y = Mathf.Cos(ang * i) * arr[i] * per;
//添加頂點
vh.AddVert(new Vector3(x, y, 0), color, Vector4.zero);
}
//描邊頂點
for (int i = 0; i < arr.Length; i++)
{
float x = Mathf.Sin(ang * i) * arr[i] * per;
float y = Mathf.Cos(ang * i) * arr[i] * per;
//添加頂點
vh.AddVert(new Vector3(x, y, 0), sideColor, Vector4.zero);
float x1 = Mathf.Sin(ang * i) * (arr[i] * per - thick);
float y1 = Mathf.Cos(ang * i) * (arr[i] * per - thick);
//添加頂點
vh.AddVert(new Vector3(x1, y1, 0), sideColor, Vector4.zero);
}
//前4個頂點被用來繪制背景圖了
//所以全部+4
//設(shè)置雷達圖渲染順序
for (int i = 0; i < arr.Length; i++)
{
if (i == 0)//0的時候算最后一個
{
vh.AddTriangle(0 + 4, arr.Length + 4, 1 + 4);
}
else
{
vh.AddTriangle(0 + 4, i + 4, (i + 1) + 4);
}
}
//前邊有雷達圖
//所以全部+4 + arr.Length
//設(shè)置描邊渲染順序
for (int i = 0; i < arr.Length; i++)
{
if (i == 0)//0的時候算最后一個
{
//9,1,2
vh.AddTriangle((arr.Length * 2 - 1) + 4 + arr.Length, 1 + 4 + arr.Length, 1 * 2 + 4 + arr.Length);
//9,2,10
vh.AddTriangle((arr.Length * 2 - 1) + 4 + arr.Length, 1 * 2 + 4 + arr.Length, (arr.Length * 2) + 4 + arr.Length);
}
else
{
vh.AddTriangle((i * 2 - 1) + 4 + arr.Length, ((i + 1) * 2 - 1) + 4 + arr.Length, ((i + 1) * 2) + 4 + arr.Length);
vh.AddTriangle((i * 2 - 1) + 4 + arr.Length, ((i + 1) * 2) + 4 + arr.Length, (i * 2) + 4 + arr.Length);
}
}
//計算半徑與傳入的最大值的比值
float per2 = rMax / arr2.Max();
//計算每個角的弧度
float ang2 = Mathf.PI * 2 / arr2.Length;
//添加圓心頂點
vh.AddVert(new Vector3(0, 0, 0), arr2Color, Vector4.zero);
for (int i = 0; i < arr2.Length; i++)
{
float x = Mathf.Sin(ang2 * i) * arr2[i] * per2;
float y = Mathf.Cos(ang2 * i) * arr2[i] * per2;
//添加頂點
vh.AddVert(new Vector3(x, y, 0), arr2Color, Vector4.zero);
}
//描邊頂點
for (int i = 0; i < arr2.Length; i++)
{
float x = Mathf.Sin(ang2 * i) * arr2[i] * per2;
float y = Mathf.Cos(ang2 * i) * arr2[i] * per2;
//添加頂點
vh.AddVert(new Vector3(x, y, 0), side2Color, Vector4.zero);
float x1 = Mathf.Sin(ang2 * i) * (arr2[i] * per2 - thick);
float y1 = Mathf.Cos(ang2 * i) * (arr2[i] * per2 - thick);
//添加頂點
vh.AddVert(new Vector3(x1, y1, 0), side2Color, Vector4.zero);
}
//前4個頂點被用來繪制背景圖了
//所以全部+4 + arr.Length * 3
int n = 5 + arr.Length * 3;
//設(shè)置雷達圖渲染順序
for (int i = 0; i < arr2.Length; i++)
{
if (i == 0)//0的時候算最后一個
{
vh.AddTriangle(0 + n, arr2.Length + n, 1 + n);
}
else
{
vh.AddTriangle(0 + n, i + n, (i + 1) + n);
}
}
//前邊有雷達圖
//所以全部+4 + arr2.Length + arr.Length * 3
int m = 5 + arr2.Length + arr.Length * 3;
//設(shè)置描邊渲染順序
for (int i = 0; i < arr2.Length; i++)
{
if (i == 0)//0的時候算最后一個
{
//例如:9,1,2
vh.AddTriangle((arr2.Length * 2 - 1) + m, 1 + m, 1 * 2 + m);
//例如:9,2,10
vh.AddTriangle((arr2.Length * 2 - 1) + m, 1 * 2 + m, (arr2.Length * 2) + m);
}
else
{
vh.AddTriangle((i * 2 - 1) + m, ((i + 1) * 2 - 1) + m, ((i + 1) * 2) + m);
vh.AddTriangle((i * 2 - 1) + m, ((i + 1) * 2) + m, (i * 2) + m);
}
}
}
}
調(diào)用方法大致如下:
public void OnBtnAttributes()
{
radarChart.arr = radarChart.arr2;
float[] newarr = new float[5];
for (int i = 0; i < 5; i++)
{
newarr[i] = Random.Range(0, 100);
attr.GetComponentsInChildren<Text>()[i].text = "屬性" + i + ":" + newarr[i];
}
radarChart.arr2 = newarr;
radarChart.SetVerticesDirty();
}