最近产品提了个需求,做游戏内个人数据分析雷达图,类似王者荣耀对战资料图,如下:

二次修改取消了五个点位显示,最后实际效果图如下:



编写[UIRader]脚本,并把五个顶点挂在脚本上,用于写入顶点坐标并实时计算三角形绘制图形。[如需要可根据顶点坐标绘制描边],如下:
using UnityEngine;
using System.Collections;
/// <summary>
/// 雷达图实现
/// </summary>
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class UIRadar : MonoBehaviour
{
/// <summary>
/// 半径
/// </summary>
public int radius;
/// <summary>
/// 每个顶点相对半径的比例
/// </summary>
public float[] scales;
/// <summary>
/// 放在顶点位置的物体
/// </summary>
public Transform[] points;
/// <summary>
/// 顶点数组
/// </summary>
[HideInInspector]
private Vector3[] vertices;
/// <summary>
/// 三角形数组
/// </summary>
private int[] triangles;
private MeshFilter meshFilter;
private Mesh mesh;
//画线组件
private LineRenderer lRender;
private void Awake()
{
CreateMesh();
SetVertices();
}
/// <summary>
/// 创建Mesh
/// </summary>
private void CreateMesh()
{
meshFilter = gameObject.GetComponent<MeshFilter>();
if (meshFilter == null)
{
meshFilter = gameObject.AddComponent<MeshFilter>();
}
mesh = meshFilter.mesh;
lRender = transform.Find("Line").GetComponent<LineRenderer>();
}
/// <summary>
/// 设置Mesh顶点
/// </summary>
private void SetVertices()
{
if (scales != null && scales.Length > 0 && mesh != null)
{
triangles = new int[scales.Length * 3];
vertices = new Vector3[scales.Length + 1];
//以中心为原点构建三角形
vertices[0] = new Vector3(0, 0, 0);
//每个顶点坐标,以Y轴为0度旋转 0-360度
float everyAngle = 360 / scales.Length;
for (int i = 1; i < vertices.Length; i++)
{
float angle = Mathf.PI / 180 * everyAngle * (i - 1);
vertices[i] = scales[i - 1] * radius * new Vector3(Mathf.Sin(angle), Mathf.Cos(angle), 0);
//刷新物体位置
if (points[i - 1] != null)
{
points[i - 1].localPosition = vertices[i];
}
}
//计算三角形
int index = 0;
int value = 0;
for (int i = 0; i < triangles.Length; i++)
{
if (i % 3 == 0)
{
triangles[i] = 0;
value = index;
index++;
}
else
{
value++;
if (value == vertices.Length)
{
value = 1;
}
triangles[i] = value;
}
}
//刷新顶点和三角形
mesh.vertices = vertices;
mesh.triangles = triangles;
}
}
/// <summary>
/// 设置某个顶点的比例
/// </summary>
/// <param name="index"></param>
/// <param name="scale"></param>
public void SetScale(int index, float scale)
{
if (index < scales.Length)
{
scales[index] = scale;
}
}
/// <summary>
/// 刷新顶点
/// </summary>
public void Refresh()
{
if (mesh != null && meshFilter != null)
{
SetVertices();
DrawingOutline();
}
else
{
Debug.LogError("Please run application first.");
}
}
/// <summary>
/// 绘制描边
/// </summary>
public void DrawingOutline()
{
//lRender.material = new Material(Shader.Find("Particles/Additive"));
lRender.startColor = new Color(0.565f, 1.000f, 0.996f, 1.000f);
lRender.endColor = new Color(0.565f, 1.000f, 0.996f, 1.000f);
lRender.startWidth = 2f;
lRender.endWidth = 2f;
Vector3[] outlineVec = new Vector3[points.Length + 1];
for (int i = 0; i < points.Length; i++)
{
outlineVec[i] = points[i].localPosition;
}
outlineVec[outlineVec.Length - 1] = points[0].localPosition;
lRender.SetPositions(outlineVec);
lRender.enabled = true;
}
}
画线描边和绘制图形应该给可以进一步优化,目前暂时先这样,后续更新调整。