天天看點

Unity 關于UGUI雷達圖實作

背景

遊戲開發中,為了可以明确看到玩家的各個數值資訊相對情況(比如:某農藥遊戲,一局結束,用雷達圖顯示玩家,參團,輸出等資訊,雷達圖顯示一目了然,友善玩家了解自己每局發揮狀态等)是以,雷達圖在表現上具有一定的優勢。

實作

實作方式主要使用VertexHelper類,重寫Image類通過擷取頂點位置,繪畫出,幾個頂點之間的區域,頂點的位置通過三角函數指派,完成位置重置。

核心代碼

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class RadarChart : Image
{
    [SerializeField]
    private int _pointCount;
    [SerializeField]
    private List<RectTransform> _points;
    [SerializeField]
    private Vector2 _pointSize = new Vector2(10, 10);
    [SerializeField]
    private Sprite _pointSprite;
    [SerializeField]
    private Color _pointColor = Color.white;
    [SerializeField]
    private float[] _handlerRadio;
    [SerializeField]
    private List<RadarChartHandler> _handlers; 

    // Update is called once per frame
    void Update()
    {
        SetVerticesDirty();
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        AddVerts(vh);
        AddTriangle(vh);
    }

    private void AddVerts(VertexHelper vh)
    {
        foreach (RadarChartHandler handler in _handlers)
        {
            vh.AddVert(handler.transform.localPosition, color, Vector2.zero);
        }
    }

    private void AddVertsTemplete(VertexHelper vh)
    {
        vh.AddVert(_handlers[0].transform.localPosition, color, new Vector2(0.5f,1));
        vh.AddVert(_handlers[1].transform.localPosition, color, new Vector2(0f, 1));
        vh.AddVert(_handlers[2].transform.localPosition, color, new Vector2(0f, 0));
        vh.AddVert(_handlers[3].transform.localPosition, color, new Vector2(1f, 0));
        vh.AddVert(_handlers[4].transform.localPosition, color, new Vector2(1f, 1));
    }

    private void AddTriangle(VertexHelper vh)
    {
        for (int i = 1; i < _pointCount - 1; i++)
        {
            vh.AddTriangle(0,i+1,i);
        }
    }

    public void InitPoint()
    {
        ClearPoints();
        _points = new List<RectTransform>();
        SpawnPoint();
        SetPointPos();
    }

    private void ClearPoints()
    {
        if(_points == null)
            return;

        foreach (RectTransform point in _points)
        {
            if(point != null)
                DestroyImmediate(point);
        }
    }

    private void SpawnPoint()
    {
        for (int i = 0; i < _pointCount; i++)
        {
            GameObject point = new GameObject("Point" + i);
            point.transform.SetParent(transform);
            _points.Add(point.AddComponent<RectTransform>());
        }
    }

    private void SetPointPos()
    {
        float radian = 2 * Mathf.PI / _pointCount;
        float radius = 100;

        float curRadian = 2 * Mathf.PI / 4.0f;
        for (int i = 0; i < _pointCount; i++)
        {
            float x = Mathf.Cos(curRadian) * radius;
            float y = Mathf.Sin(curRadian) * radius;
            curRadian += radian;
            _points[i].anchoredPosition = new Vector2(x, y);
        }
    }

    public void InitHandlers()
    {
        ClearHandlers();
        _handlers = new List<RadarChartHandler>();
        SpawnHandlers();
        SetHandlerPos();
    }

    private void ClearHandlers()
    {
        if (_handlers == null)
            return;

        foreach (RadarChartHandler handler in _handlers)
        {
            if (handler != null)
                DestroyImmediate(handler.gameObject);
        }
    }

    private void SpawnHandlers()
    {
        RadarChartHandler handler = null;
        for (int i = 0; i < _pointCount; i++)
        {
            GameObject point = new GameObject("Handler" + i);
            point.AddComponent<RectTransform>();
            point.AddComponent<Image>();
            handler = point.AddComponent<RadarChartHandler>();
            handler.SetParent(transform);
            handler.ChangeSprite(_pointSprite);
            handler.ChangeColor(_pointColor);
            handler.SetSize(_pointSize);
            handler.SetScale(Vector3.one);
            _handlers.Add(handler);
        }

    }

    private void SetHandlerPos()
    {
        if (_handlerRadio == null || _handlerRadio.Length != _pointCount)
        {
            for (int i = 0; i < _pointCount; i++)
            {
                _handlers[i].SetPos(_points[i].anchoredPosition);
            }
        }
        else
        {
            for (int i = 0; i < _pointCount; i++)
            {
                _handlers[i].SetPos(_points[i].anchoredPosition * _handlerRadio[i]);
            }
        }
    }
}

           

示範圖檔:

Unity 關于UGUI雷達圖實作

視訊示範連結:

https://live.csdn.net/v/146961

Demo_025下載下傳連結:

連結:https://pan.baidu.com/s/1CP4FLttldNHW-gW2zUrlDA

提取碼:ncv6