欢迎光临散文网 会员登陆 & 注册

Unity雷达制作(一)

2021-11-02 23:17 作者:柯昌弟弟c  | 我要投稿


自己做的游戏的样子

非常好用的一款雷达图,直接把代码分享给大家。

UIRadarGraphManager.cs

using UnityEngine;

using UnityEngine.UI;


[System.Serializable]

public struct GraphData

{

    public string _desc;

    [Range(0, 100)]

    public float _value;


    public float Rate

    {

        get

        {

            return _value / 100;

        }

    }


    public GraphData(string desc, float value)

    {

        _desc = desc;

        _value = value;

    }

}

public class UIRadarGraphManager : MaskableGraphic

{

    public GraphData[] _datas;

    public int _rulingCount = 4;//刻度数

    public float _lineWidth = 1f;//背景线宽度

    public float _radarLineWidth = 1f;//雷达边框宽度

    public Color _lineColor = Color.gray;//背景线颜色

    public Color _radarLineColor = Color.blue;//雷达边框颜色

    public UIRadarImage _radarImage;//雷达图

    public float _tweenTime = 1f;//动画事件


    private Vector2[] _vertexs;//顶点

    private float _radius;//半径

    private float _perRadian;//弧度


    protected override void Awake()

    {

        base.Awake();

        _radius = Mathf.Min(rectTransform.sizeDelta.x, rectTransform.sizeDelta.y) / 2;

    }


    /// <summary>

    /// 刷新雷达图

    /// </summary>

    /// <param name="datas"></param>

    public void RefeshRadarGraph(GraphData[] datas)

    {

        _datas = datas;

        SetAllDirty();//设置Layout布局、Vertices顶点和Material材质为Dirty;当一个Canvas被标记为包含需要被rebatch的几何图形,那这个Canvas被认为dirty。

        _radarImage.transform.localScale = Vector3.zero;

        _radarImage.Init(datas, _radius, _radarLineWidth, _radarLineColor);

        _radarImage.transform.localScale = Vector3.one;

    }


    /// <summary>

    /// UI生成顶点时调用

    /// </summary>

    /// <param name="vh"></param>

    protected override void OnPopulateMesh(VertexHelper vh)

    {

        if (_datas == null || _datas.Length <= 2)//不可能存在边树小于三的多边形

        {

            base.OnPopulateMesh(vh);

            return;

        }

        vh.Clear();

        DrawAxis(vh);

        DrawRuling(vh);

    }


    /// <summary>

    /// 画坐标轴

    /// </summary>

    /// <param name="vh"></param>

    private void DrawAxis(VertexHelper vh)

    {

        GetVertexs();

        for (int i = 0; i < _vertexs.Length; i++)

        {

            vh.AddUIVertexQuad(GetQuad(Vector2.zero, _vertexs[i], _lineColor, _lineWidth));

        }

    }


    /// <summary>

    /// 画刻度

    /// </summary>

    private void DrawRuling(VertexHelper vh)

    {

        float perRadius = _radius / (_rulingCount - 1);//原点不需要画

        for (int i = 1; i < _rulingCount; i++)

        {

            for (int j = 0; j < _datas.Length; j++)

            {

                float startRadian = _perRadian * j + 90 * Mathf.Deg2Rad;

                float endRadian = _perRadian * (j + 1) + 90 * Mathf.Deg2Rad;

                Vector2 startPos = new Vector2(Mathf.Cos(startRadian), Mathf.Sin(startRadian)) * perRadius * i;

                Vector2 endPos = new Vector2(Mathf.Cos(endRadian), Mathf.Sin(endRadian)) * perRadius * i;

                UIVertex[] newVertexs = GetQuad(startPos, endPos, _lineColor, _lineWidth);

                vh.AddUIVertexQuad(newVertexs);

            }

        }

    }

    

    /// <summary>

    /// 获取顶点

    /// </summary>

    /// <returns></returns>

    private void GetVertexs()

    {

        _perRadian = Mathf.PI * 2 / _datas.Length;

        _vertexs = new Vector2[_datas.Length];

        for (int i = 0; i < _datas.Length; i++)

        {

            float radian = _perRadian * i + 90 * Mathf.Deg2Rad;

            Vector2 endPos = new Vector2(Mathf.Cos(radian), Mathf.Sin(radian)) * _radius;

            _vertexs[i] = endPos;

        }

    }


    /// <summary>

    /// 获取一条线的四个顶点

    /// </summary>

    /// <param name="startPos"></param>

    /// <param name="endPos"></param>

    /// <returns></returns>

    private UIVertex[] GetQuad(Vector2 startPos, Vector2 endPos, Color color, float width)

    {

        float dis = Vector2.Distance(startPos, endPos);

        float x = width / 2 * (endPos.y - startPos.y) / dis;//sin

        float y = width / 2 * (endPos.x - startPos.x) / dis;//cos

        if (y <= 0) y = -y;

        else x = -x;

        UIVertex[] vertex = new UIVertex[4];

        vertex[0].position = new Vector3(startPos.x + x, startPos.y + y);

        vertex[1].position = new Vector3(endPos.x + x, endPos.y + y);

        vertex[2].position = new Vector3(endPos.x - x, endPos.y - y);

        vertex[3].position = new Vector3(startPos.x - x, startPos.y - y);

        for (int i = 0; i < vertex.Length; i++)

            vertex[i].color = color;

        return vertex;

    }


}

UIRadarImage.cs

using UnityEngine;

using UnityEngine.UI;


public class UIRadarImage : MaskableGraphic

{

    [HideInInspector]

    public GraphData[] _datas;

    [HideInInspector]

    public float _radius;

    [HideInInspector]

    public float _lineWidth;

    [HideInInspector]

    public Color _lineColor;


    private float _perRadian;//弧度


    /// <summary>

    /// 初始化

    /// </summary>

    /// <param name="datas"></param>

    /// <param name="radius"></param>

    /// <param name="lineWidth"></param>

    /// <param name="lineColor"></param>

    public void Init(GraphData[] datas, float radius, float lineWidth, Color lineColor)

    {

        _datas = datas;

        _radius = radius;

        _lineWidth = lineWidth;

        _lineColor = lineColor;

        SetAllDirty();//设置Layout布局、Vertices顶点和Material材质为Dirty;我认为是重新绘制

    }


    /// <summary>

    /// 填充网格

    /// </summary>

    /// <param name="vh"></param>

    protected override void OnPopulateMesh(VertexHelper vh)

    {

        if (_datas == null || _datas.Length <= 2)//不可能存在边数小于三的多边形

        {

            base.OnPopulateMesh(vh);

            return;

        }

        vh.Clear();

        _perRadian = Mathf.PI * 2 / _datas.Length;

        DrawRadar(vh);

        DrawLine(vh);

    }


    /// <summary>

    /// 画雷达图

    /// </summary>

    /// <param name="vh"></param>

    private void DrawRadar(VertexHelper vh)

    {

        int edgeCount = _datas.Length;//边数量

        //画雷达三角面

        for (int i = 0; i < edgeCount; i++)

        {

            DrawTriangle(vh, GetVertex(i), i);

        }

    }


    /// <summary>

    /// 画雷达图边框

    /// </summary>

    /// <param name="vh"></param>

    private void DrawLine(VertexHelper vh)

    {

        int edgeCount = _datas.Length;//边数量

        //画雷达三角面

        for (int i = 0; i < edgeCount; i++)

        {

            DrawLine(vh, GetVertex(i));

        }

    }


    /// <summary>

    /// 画三角面

    /// </summary>

    /// <param name="vh"></param>

    /// <param name="index"></param>

    /// <param name="deltaAngle"></param>

    private void DrawTriangle(VertexHelper vh, Vector3[] poses, int index)

    {

        Color color = _lineColor;

        color.a = 0.5f;


        vh.AddVert(Vector3.zero, color, Vector2.zero);//中心点

        vh.AddVert(poses[0], color, Vector2.zero);

        vh.AddVert(poses[1], color, Vector2.zero);//UI的法线可以随便设置

        vh.AddTriangle(index * 3, index * 3 + 1, index * 3 + 2);//将三角面加入UI绘制缓冲区。参数是三角面的三个顶点索引//所以绘制n边形需要绘制3n的顶点

    }


    /// <summary>

    /// 画线

    /// </summary>

    /// <param name="vh"></param>

    /// <param name="index"></param>

    private void DrawLine(VertexHelper vh, Vector3[] poses)

    {

        //画线

        UIVertex[] newVertexs = GetQuad(poses[0], poses[1], _lineColor, _lineWidth);

        vh.AddUIVertexQuad(newVertexs);

    }


    /// <summary>

    /// 获取一个弧度的两个顶点

    /// </summary>

    /// <param name="index"></param>

    /// <returns></returns>

    private Vector3[] GetVertex(int index)

    {

        int nextIndex = index + 1 >= _datas.Length ? 0 : index + 1;

        float radian1 = index * _perRadian + 90 * Mathf.Deg2Rad;

        float radian2 = nextIndex * _perRadian + 90 * Mathf.Deg2Rad;

        float radius1 = _datas[index].Rate * _radius;

        float radius2 = _datas[nextIndex].Rate * _radius;

        //两边顶点

        Vector3 p1 = new Vector3(radius1 * Mathf.Cos(radian1), radius1 * Mathf.Sin(radian1));

        Vector3 p2 = new Vector3(radius2 * Mathf.Cos(radian2), radius2 * Mathf.Sin(radian2));

        return new Vector3[] { p1, p2 };

    }


    /// <summary>

    /// 获取一条线的四个顶点

    /// </summary>

    /// <param name="startPos"></param>

    /// <param name="endPos"></param>

    /// <returns></returns>

    private UIVertex[] GetQuad(Vector2 startPos, Vector2 endPos, Color color, float width)

    {

        float dis = Vector2.Distance(startPos, endPos);

        float x = width / 2 * (endPos.y - startPos.y) / dis;//sin

        float y = width / 2 * (endPos.x - startPos.x) / dis;//cos

        if (y <= 0) y = -y;

        else x = -x;

        UIVertex[] vertex = new UIVertex[4];

        vertex[0].position = new Vector3(startPos.x + x, startPos.y + y);

        vertex[1].position = new Vector3(endPos.x + x, endPos.y + y);

        vertex[2].position = new Vector3(endPos.x - x, endPos.y - y);

        vertex[3].position = new Vector3(startPos.x - x, startPos.y - y);

        for (int i = 0; i < vertex.Length; i++)

            vertex[i].color = color;

        return vertex;

    }

}

直接传入数据即可

     GetComponent<UIRadarGraphManager>().RefeshRadarGraph(graphDatas);


此代码是之前网上学到的,原链接找不到啦,不过非常具有学习价值。

Unity雷达制作(一)的评论 (共 条)

分享到微博请遵守国家法律