Unity中制作雷达数据图(类王者荣耀对战资料)

1,074 阅读2分钟

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

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

以下是具体实现方法: 首先创建一个带[MeshFilter]及[MeshRenderer]组件的Rader预制体,所需材质则根据你需要的颜色透明度自行创建。而后在此预制体下挂五个标记点位,用于标记动态绘制。(如像我一样需要描边,则另外挂一个Line预制并带上画线组件[LineRenderer])。至于Rader上挂的[UIRader]脚本用处及脚本下面会贴出来。如图:

编写[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;
    }

}

画线描边和绘制图形应该给可以进一步优化,目前暂时先这样,后续更新调整。