资讯详情

王者荣耀中的技术,技能冷却原来是这样做的

圆形图片常用于游戏中,常见的场景如王者荣耀技能图标,但是Unity发动机本身没有提供类似的组件,需要开发人员自己实现。本文主要介绍了两种简单的圆形图片实现方法,并提供了一种实现技能CD以及精确的技能响应方法。 在这里插入图片描述

一、Mask遮罩实现

过程:创建一个父物,添加到父物中Mask和Image组件,并为Image添加圆形镂空图片,创建子物体添加Image组件,给Image添加想要实现圆形效果的图片。

可见锯齿效果明显,这是因为我给父物添加的背景图比较拉跨,是的Unity自带的Knob,可以去选择其他圆形背景来优化一下锯齿效果。

二、实现自定义

任何物体的显示过程都是通过的CPU首先计算顶点信息GPU绘制并最终显示在屏幕上,因此我们可以改变需要绘制的顶部信息以修改显示效果。首先需要了解以下预先信息:

1、OnPopulateMesh

该方法是Image中的一个可重写的方法protectedoverridevoidOnPopulateMesh(VertexHelper toFill)VectexHelper是存储绘图顶点信息的载体,GPU图形将根据参数中的信息绘制。我们可以自定义继承Image并重新实现该方法VertexHelper 只存储我们想要显示的顶点。

2、UV

UV它是一种二维坐标信息,可以简单地看作是四位向量(x,y,z,w)

可以使用上述矩形位置信息x,y,z,w由于需要使用四个数字来表示系统底层UV而在Unity世界坐标被用来将图片的位置信息转换为UV坐标就可以了。

3、坐标转换

如何将图片的位置信息转换为相应的UV坐标呢?比如一张图4000。*400,我们可以通过工具类获得图片UV比如坐标长度是(0、0、1、1),那么原始图片上的点是如何映射到的呢?UV在坐标上,它们之间有一个比例转换系数。

宽高对应比例缩放,计算出缩放系数后,那么对于原始图片上的任一点,我们都能得到在UV相应的坐标信息。

4.圆是怎么显示的?

我们知道在计算机底层根本不知道圆圈,圆是由多个三角形、三角形、四边形、五边形、六边形、十边形、N边形,它们的形状越来越接近圆形。

当图中有足够的三角形时,我们看到的形状越接近圆,当给定圆半径时R,当给定该圆由多少三角形组成时,我们可以计算每个三角形的弧度Radian,根据勾股定理不难得出A,B与圆心O坐标相比。

5、代码实现

为了方便理解,我尽量添加注释。如果只是想实现功能,请直接copy可以挂载脚本。

  • 外层P:实际图片对应的矩形

  • 内层Circle:想要图片显示的样子

  • 任务:计算点A坐标赋值uvTemp.position 并将点A在UV相应的坐标赋值uvTemp.uv0

  • 第一步:1、我们需要先确定O点的坐标,可以先记(0,0),A点击实际坐标即可记录 uvTemp.position = (0,0) (X,Y)

    2.最后,按比例转换UV坐标uvTemp.uv0 = new Vector2(xy.x * convertRatio.x uvCenter.x, xy.y * convertRatio.y uvCenter.y);

6、完整代码

using System.Collections.Generic; using UnityEngine; using UnityEngine.Sprites; using UnityEngine.UI;  public class CircleImage : Image {     [SerializeField] private float showPercent = 1f;     [SerializeField] private int segments = 100;protected override void OnPopulateMesh(VertexHelper vh) {     vh.Clear();      float width = rectTransform.rect.width;     float height = rectTransform.rect.height;     Vector2 uv = GetUV(overrideSprite);     Vector2 convertRatio = GetConvetRatio(uv.x, uv.y, width, height);     Vector2 uvCenter = GetUvCenter(uv.x, uv.y);     Vector2 originPos = GetOriginPos(width, height);     UIVertex origin = new UIVertex();     ///设置原始颜色渐变     byte c = (byte) (showPercent * 255);     origin.color = new Color32(c, c, c, 255);     origin.position = originPos;     origin.uv0 = new Vector2(Vector2.zero.x * convertRatio.x   uvCenter.x,         Vector2.zero.y * convertRatio.y   uvCenter.y);     vh.AddVert(origin);      float radian = Mathf.PI * 2 / segments;     float curRadian = 0;     float radius = width * 0.5f;     int realSegment = (int) (showPercent * segments);     for (int i = 0; i < segments   1; i  )     {         float x = Mathf.Cos(curRadian) * radius;         float y = Mathf.Sin(curRadian) * radius;         curRadian  = radian;         Vector2 xy = new Vector2(x, y);         UIVertex uvTemp = new UIVertex();         if (i < realSegment)         {             uvTemp.color = color;         }         else         {             if (realSegment == segments)             {                 uvTemp.color = color;             }             else             {                 uvTemp.color = new Color32(60, 60, 60, 255);             }         }          uvTemp.position = xy   originPos;         uvTemp.uv0 = new Vector2(xy.x * convertRatio.x   uvCenter.x, xy.y * convertRatio.y   uvCenter.y);         vh.AddVert(uvTemp);     }      int id = 1;     for (int i = 0; i < segments; i  )     {         vh.AddTriangle(id, 0, id   1);         id  ;     } }  private Vector2 GetConvetRatio(float uvWidth, float uvHeight, float width, float height) {     Vector2 convertRatio = new Vector2(uvWidth / width, uvHeight / height);     return convertRatio; }  private Vector2 GetUvCenter(float uvWidth, float uvHeight) {     Vector2 center = new Vector2(uvWidth * 0.5f, uvHeight * 0.5f);     return center; }  private Vector2 GetOriginPos(float width, float height) {     Vector2 originPos =         new Vector2((0.5f - rectTransform.pivot.x) * width, ((0.5f - rectTransform.pivot.y) * height));     return originPos; }  private Vector2 GetUV(Sprite sprite) {     Vector4 temp = sprite!= null ? DataUtility.GetOuterUV(sprite) : Vector4.zero;
    float uvHeight = temp.w - temp.y;
    float uvWidth = temp.z - temp.x;
    Vector2 uv = new Vector2(uvWidth, uvHeight);
    return uv;
}

}

7、视频效果

8、总结

实现圆形图片还是比较简单的,特别是CD效果,也是控制三角形定点实现的。

欢迎搜索关注微信公众号,这里有 一只会Coding的柴柴等你哦~

标签: 冷却水回水流量断流报警传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台