首页 > 其他分享 >Unity绘制圆和缓动雷达图

Unity绘制圆和缓动雷达图

时间:2023-03-21 23:48:22浏览次数:51  
标签:vh float texture Unity 和缓 绘制 public rect

Unity绘制圆和缓动雷达图

之前在做UI模块的时候遇到过需要做雷达图的效果,所以简单复习了一下

关于网格绘制

我们都知道Unity绘制图形是通过Mesh网格添加顶点进行绘制,那么知道顶点信息后如何实现图形的绘制,就是由Graphic类来帮助我们实现。因此我们需要自定义一个类继承Graphic,然后重写其OnPopulateMesh方法,将其挂载到UI物体上。

public class RadarMap : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        
​    }
}

注:若想要支持RectMask2D功能,则改为继承MaskableGraphic即可

OnPopulateMesh方法中提供了VertexHelper参数,这是Unity的顶点辅助类,通过它我们可以轻松实现添加顶点和绘制等操作了。

添加顶点

//参数是顶点坐标,颜色以及uv坐标
new VertexHelper().AddVert(Vector3 position, Color32 color, Vector2 uv0)

顶点的绘制

new VertexHelper().AddTriangle(int idx0, int idx1, int idx2);

绘制圆

对于Unity中的网格,我们只能通过一个个三角形拼接成不同的形状,包括Unity本身的物体网格也是如此,因此,画圆可以通过弧度和半径,以及圆的边长去绘制多个三角形,拼接而成一个圆

这是对画圆的一些总结

画圆的代码如下:

using UnityEngine;
using UnityEngine.UI;

public class RadarMap : Graphic
{
    public Texture2D texture;
    public Color _color = Color.white;
    public int n;
    public float r;
    public override Texture mainTexture//赋值UI图片
    {
        get
        {
            if (texture != null)
            {
                return texture;//如果有外部精灵则返回外部精灵的texture
            }
            if (material != null && material.mainTexture != null)
            {
                return material.mainTexture;//如果有材质则返回材质上的texture
            }
            return s_WhiteTexture;//什么都没有的情况返回默认的texture
        }
    }
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        Rect rect = rectTransform.rect;
        r = rect.width < rect.height ? rect.width / 2 : rect.height / 2;//取当前最小的宽或高,取一半获得半径
        if (n >= 3)
        {
            vh.Clear();
            vh.AddVert(Vector3.zero, color, new Vector2(0.5f, 0.5f));//添加圆心点
            float ang = 2 * Mathf.PI / n;
            for (int i = 0; i < n; i++)
            {
                float x = Mathf.Sin(i * ang) * r;
                float y = Mathf.Cos(i * ang) * r;

                float uvx = (x + r) / (2 * r);//通过圆上点+半径/直径求出uv坐标
                float uvy = (y + r) / (2 * r);
                vh.AddVert(new Vector3(x, y, 0), color, new Vector3(uvx, uvy));//添加顶点
                if (i == 0)
                {
                    vh.AddTriangle(0, n, 1);//第一次绘制最后一部分
                }
                else
                {
                    vh.AddTriangle(0, i, i + 1);//依次绘制
                }
            }
        }
    }
}

画出圆的效果

绘制雷达图

根据绘制圆我们可以发现,绘制雷达图是同理的,同样是添加一个圆心点并根据半径和弧度求出圆上的顶点,只是雷达图每个顶点的位置都跟雷达图中的数值有关。因此,我们只需要添加一个数组,并将画圆的代码稍作修改就可以了

以下是雷达图的绘制代码:

using UnityEngine;
using UnityEngine.UI;
public class RadarMap : Graphic
{
    public Texture2D texture;
    public Color _color = Color.white;
    public float[] arr = new float[0];
    public float r;
    public override Texture mainTexture
    {
        get
        {
            if (texture != null)
            {
                return texture;//如果有外部精灵则返回外部精灵的texture
            }
            if (material != null && material.mainTexture != null)
            {
                return material.mainTexture;//如果有材质则返回材质上的texture
            }
            return s_WhiteTexture;//什么都没有的情况返回默认的texture
        }
    }
    //生成无背景雷达图 这里的生成方法和生成圆的方法是一致的
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        Rect rect = rectTransform.rect;
        int n = arr.Length;
        //取当前最小的宽或高,取一半获得半径
        r = rect.width < rect.height ? rect.width / 2 : rect.height / 2;
        if (n >= 3)
        {
            vh.Clear();
            //添加圆心点
            vh.AddVert(Vector3.zero, color, new Vector2(0.5f, 0.5f));
            float ang = 2 * Mathf.PI / n;
            for (int i = 0; i < n; i++)
            {
                //通过数组中数据的值为雷达图赋值,最大值为半径
                float x = Mathf.Sin(i * ang) * (arr[i] < r ? arr[i] : r);
                float y = Mathf.Cos(i * ang) * (arr[i] < r ? arr[i] : r);
                //通过圆上点+半径/直径求出uv坐标
                float uvx = (x + r) / (2 * r);
                float uvy = (y + r) / (2 * r);
                //添加顶点
                vh.AddVert(new Vector3(x, y, 0), color, new Vector3(uvx, uvy));
                if (i == 0)
                {
                    //第一次绘制最后一部分
                    vh.AddTriangle(0, n, 1);
                }
                else
                {
                    //依次绘制
                    vh.AddTriangle(0, i, i + 1);
                }
            }
        }
    }
}

最后的效果如下

缓动则通过Mathf.Lerp的差值函数实现,也可以直接使用公式( max - min ) * p + min

代码如下:

//缓动代码块,这里的数组和集合已经赋值过
public RadarMap radarMap;
bool isDrow = false;
List<float> arr = new List<float>();
float[] arry;
float MaxTime = 3f;//缓动最大时间
float nowTime = 0f;//缓动开始时间
private void Update()
{
    if (isDrow)
    {
        nowTime += Time.deltaTime;
        for (int i = 0; i < arr.Count; i++)
        {
            //差值函数,始终在当前点和目标点中间取一个参数
            arry[i] = Mathf.Lerp(0, arr[i], nowTime / MaxTime);
            //当达到了这个值以后,循环结束,清空缓存原始数据的集合
            if (i == arr.Count - 1 && arr[i] - arry[i] <= 0.1f)
            {
                Mathf.Round(arry[i]);
                arr.Clear();
                isDrow = false;
                nowTime = 0f;
            }
        }
        //清除脏数据
        radarMap.SetAllDirty();
        //将每次算出的差值赋给RadarMap
        radarMap.arr = arry;
    }
}

标签:vh,float,texture,Unity,和缓,绘制,public,rect
From: https://www.cnblogs.com/x-zhi/p/17242057.html

相关文章

  • 【Unity3D】空间和变换
    1空间1.1左右手坐标系及其法则1.1.1左右手坐标系左手坐标系与右手坐标系​Unity局部空间、世界空间、裁剪空间、屏幕空间都采用左手坐标系,只有观察空间采用右......
  • 【Unity3D】激光灯、碰撞特效
    1需求描述​本文将模拟激光灯(或碰撞)特效,详细需求如下:从鼠标位置发射屏幕射线,检测是否与物体发生碰撞当与物体发生碰撞时,在物体表面覆盖一层激光灯(或碰撞)特效​......
  • HTTP协议分析与Unity用法
    一、http协议简介http协议是HyperTextTransferProtocol(超文本传输协议)的缩写,是用于从万维网服务器传输超文本到本地浏览器的传送协议,使用TCP/IP通信协议传输数据,面向......
  • cocos creator教程:嵌入 unity
    使用配置unity2021.3.20f1c1cocoscreator3.6.1unity配置1.配置原生环境顶部菜单/文件/生成设置,以IOS为例2.配置APILevel和cocos打包配置一致接入步......
  • Revit 机电模型导入 Unity(一)
    Revit机电模型导入Unity(一)目前存在问题1.Revit机电模型导出带材质的模型到Unity2.Revit机电模型颜色是通过过滤器(仅改变视图并未改变实际材质颜色)实现分类,......
  • 【Unity3D】基于模板测试和顶点膨胀的描边方法
    1前言​选中物体描边特效中介绍了基于模板纹理模糊膨胀的描边方法,该方法实现了软描边,效果较好,但是为了得到模糊纹理,对屏幕像素进行了多次渲染,效率欠佳。本文将介绍......
  • 【Unity3D】基于AssetBundle实现资源热更新
    1前言​Unity3D本地资源一般放在Resources目录下,但是Resouces文件夹的大小不能超过2G,使用AssetBundle管理资源可以解决Resources文件夹受限问题。​......
  • 【Unity3D】半球卷屏特效
    1原理​凸镜贴图和渐变凸镜贴图中介绍了使用OpenGL实现凸镜贴图及其原理,通过顶点坐标映射到纹理坐标,并构造三角形网格,构建了真正的三维凸镜模型。本文通过Shad......
  • 【Unity3D】卷轴特效
    1原理​当一个圆在地面上沿直线匀速滚动时,圆上固定点的运动轨迹称为旋轮线(或摆线、圆滚线)。本文实现的卷轴特效使用了旋轮线相关理论。​以下是卷轴特效原理及......
  • 【Unity3D】水波特效
    1水波特效原理​水波特效属于Unity3D后处理特效,其原理是:对渲染后的纹理进行局部挤压和拉升变换,即对局部uv坐标进行周期性的偏移运动,实现波纹效果。​1)波形......