目的:

游戏中经常会用到进度条,但是美术给的图片用filled一拉伸就很难看,如下图

UGUI——重写Image类实现进度条

第一种模式是九宫格模式,第二种是filled。而我们需要的是两种可结合的。

如何实现:

新建一个类,继承image类后,我选择改写sliced模式下的渲染方式,将horizont填充方式的功能添加进去。

因为大部分进度条只需要切割左右两头,所以为了省事只实现了“三宫格”,并且两头切割的长度要相等。

然而inspector中的sliced模式下不包括fillmount属性,所以我们还需要改写ImageEditor,也是新建类继承。

注意继承ImageEditor的文本要放在Asset文件夹下的Editor文件夹里,unity会自动编译添加的。

代码:

  1 using System.Collections;
  2 using System.Collections.Generic;
  3 using UnityEngine;
  4 using UnityEngine.UI;
  5 using UnityEngine.Sprites;
  6 
  7 public class childImage :  Image{
  8     
  9     protected override void OnPopulateMesh(VertexHelper toFill)
 10     {
 11         base.OnPopulateMesh(toFill);
 12         if (overrideSprite == null)
 13         {
 14             base.OnPopulateMesh(toFill);
 15             return;
 16         }
 17         if (type == Type.Sliced)
 18         {
 19             GenerateSlicedSprite_(toFill);
 20         }
 21     }
 22 
 23     Vector4 GetAdjustedBorders(Vector4 border, Rect rect)
 24     {
 25         for (int axis = 0; axis <= 1; axis++)
 26         {
 27             // If the rect is smaller than the combined borders, then there's not room for the borders at their normal size.
 28             // In order to avoid artefacts with overlapping borders, we scale the borders down to fit.
 29             float combinedBorders = border[axis] + border[axis + 2];
 30             if (rect.size[axis] < combinedBorders && combinedBorders != 0)
 31             {
 32                 float borderScaleRatio = rect.size[axis] / combinedBorders;
 33                 border[axis] *= borderScaleRatio;
 34                 border[axis + 2] *= borderScaleRatio;
 35             }
 36         }
 37         return border;
 38     }
 39 
 40     static void AddQuad(VertexHelper vertexHelper, Vector2 posMin, Vector2 posMax, Color32 color, Vector2 uvMin, Vector2 uvMax)
 41     {
 42         int startIndex = vertexHelper.currentVertCount;
 43 
 44         vertexHelper.AddVert(new Vector3(posMin.x, posMin.y, 0), color, new Vector2(uvMin.x, uvMin.y));
 45         vertexHelper.AddVert(new Vector3(posMin.x, posMax.y, 0), color, new Vector2(uvMin.x, uvMax.y));
 46         vertexHelper.AddVert(new Vector3(posMax.x, posMax.y, 0), color, new Vector2(uvMax.x, uvMax.y));
 47         vertexHelper.AddVert(new Vector3(posMax.x, posMin.y, 0), color, new Vector2(uvMax.x, uvMin.y));
 48 
 49         vertexHelper.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
 50         vertexHelper.AddTriangle(startIndex + 2, startIndex + 3, startIndex);
 51     }
 52     private void GenerateSlicedSprite_(VertexHelper toFill)
 53     {
 54         Vector4 outer, inner, padding, border;
 55 
 56         if (overrideSprite != null)
 57         {
 58             outer = DataUtility.GetOuterUV(overrideSprite);
 59             inner = DataUtility.GetInnerUV(overrideSprite);
 60             padding = DataUtility.GetPadding(overrideSprite);
 61             border = overrideSprite.border;
 62         }
 63         else
 64         {
 65             outer = Vector4.zero;
 66             inner = Vector4.zero;
 67             padding = Vector4.zero;
 68             border = Vector4.zero;
 69         }
 70 
 71         Rect rect = GetPixelAdjustedRect();
 72         border = GetAdjustedBorders(border / pixelsPerUnit, rect);
 73         padding = padding / pixelsPerUnit;
 74         float condition = (border.z + border.x) / rect.width;
 75         #region 实际显示size
 76         float[] x={0,0,0,0};
 77 
 78         x[0] = 0;
 79         if (fillAmount <condition)
 80         {
 81             x[1] = fillAmount / 2 * rect.width;
 82             x[2] = x[1]+ 0;
 83             x[3] = x[1]*2;
 84         }
 85         else
 86         {
 87           x[1] = border.x;
 88           x[2] = rect.width *fillAmount-border.z;
 89           x[3] =x[2]+border.z;
 90         }
 91         float []y ={0+rect.y,rect.height+rect.y};
 92 
 93         for (int i = 0; i < 4; ++i)
 94         {
 95             x[i] += rect.x;
 96 
 97         }
 98         #endregion
 99 
100         #region uv值
101         float[] x_uv = {0,0,0,0 };
102 
103         x_uv[0] =0;
104         if (fillAmount <condition)
105         {
106             x_uv[1] = fillAmount*rect.width/2/sprite.rect.size.x;
107             x_uv[2] = 1 - x_uv[1];
108         }
109         else
110         {
111             x_uv[1] = inner.x;
112             x_uv[2] = inner.z;
113         }
114         x_uv[3] = outer.z;
115 
116         float y_uv = 1;
117         #endregion
118         
119         toFill.Clear();
120         for (int i = 0; i < 3; i++)
121         {
122             int i2 = i + 1;
123             AddQuad(toFill,
124                     new Vector2(x[i],y[0]),
125                     new Vector2(x[i2],y[1]),
126                     color,
127                     new Vector2(x_uv[i],0),
128                     new Vector2(x_uv[i2],y_uv));
129         }
130          
131     }
132 
133 
134 }
View Code

相关文章:

  • 2021-11-15
  • 2021-10-07
  • 2021-12-17
  • 2021-10-12
  • 2022-01-14
  • 2022-01-21
  • 2022-01-27
猜你喜欢
  • 2022-12-23
  • 2021-10-30
  • 2021-05-24
  • 2022-12-23
  • 2021-08-07
  • 2021-10-05
  • 2021-11-25
相关资源
相似解决方案