UGUI Gradient
在处理图片、文本的渐变效果时,为了缩减包体一般会使用插件脚本来实现,进而避免使用更多的图片资源,在网上搜索 Unity 渐变效果,一般能找到的都是单向自上而下的渐变效果,源码出处已不可考,大家感兴趣可自行搜索,本文直接给出改进版本,支持设置两端颜色和渐变的方向(上下,左右,左倾斜,右倾斜)。
实现效果
源代码
namespace UnityEngine.UI
{
using UnityEngine;
using System.Collections.Generic;
public enum GradientType
{
Horizontal,
Vertical,
LeftBank,
RightBank
}
[AddComponentMenu("UI/Effects/Gradient")]
public class Gradient : BaseMeshEffect {
public GradientType Type = GradientType.Vertical;
public Color32 StartColor = Color.white;
public Color32 EndColor = Color.black;
public override void ModifyMesh(VertexHelper helper) {
if (!IsActive() || helper.currentVertCount == 0) {
return;
}
var vertices = new List<UIVertex>();
helper.GetUIVertexStream(vertices);
// 计算中间色,倾斜时需要使用
var middleColor = Color.Lerp(StartColor, EndColor, 0.5f);
// 根据不同类型设置网格每个顶点的颜色
switch (Type)
{
case GradientType.Vertical:
for (var i = 0; i < vertices.Count && vertices.Count - i >= 6;)
{
ChangeColor(ref vertices, i + 0, StartColor);
ChangeColor(ref vertices, i + 1, StartColor);
ChangeColor(ref vertices, i + 2, EndColor);
ChangeColor(ref vertices, i + 3, EndColor);
ChangeColor(ref vertices, i + 4, EndColor);
ChangeColor(ref vertices, i + 5, StartColor);
i += 6;
}
break;
case GradientType.Horizontal:
for (var i = 0; i < vertices.Count && vertices.Count - i >= 6;)
{
ChangeColor(ref vertices, i + 0, EndColor);
ChangeColor(ref vertices, i + 1, StartColor);
ChangeColor(ref vertices, i + 2, StartColor);
ChangeColor(ref vertices, i + 3, StartColor);
ChangeColor(ref vertices, i + 4, EndColor);
ChangeColor(ref vertices, i + 5, EndColor);
i += 6;
}
break;
case GradientType.LeftBank:
for (var i = 0; i < vertices.Count && vertices.Count - i >= 6;)
{
ChangeColor(ref vertices, i + 0, StartColor);
ChangeColor(ref vertices, i + 1, middleColor);
ChangeColor(ref vertices, i + 2, EndColor);
ChangeColor(ref vertices, i + 3, EndColor);
ChangeColor(ref vertices, i + 4, middleColor);
ChangeColor(ref vertices, i + 5, StartColor);
i += 6;
}
break;
case GradientType.RightBank:
for (var i = 0; i < vertices.Count && vertices.Count - i >= 6;)
{
ChangeColor(ref vertices, i + 0, middleColor);
ChangeColor(ref vertices, i + 1, StartColor);
ChangeColor(ref vertices, i + 2, middleColor);
ChangeColor(ref vertices, i + 3, middleColor);
ChangeColor(ref vertices, i + 4, EndColor);
ChangeColor(ref vertices, i + 5, middleColor);
i += 6;
}
break;
}
helper.Clear();
helper.AddUIVertexTriangleStream(vertices);
}
private static void ChangeColor(ref List<UIVertex> verList, int index, Color color) {
var temp = verList[index];
temp.color *= color;
verList[index] = temp;
}
}
}
改进
此处提出几点改进的方向,和思路,不作出具体实现,感兴趣的可以自己实践一下,有一定挑战性。
增加中间过渡色的支持
如果需要支持过渡色,则需要对网格进行拆分,手动修改网格数据并加入指定过渡色数量的中间网格,每增加一个过渡色,需要增加两个三角形网格,计算完所有网格的坐标后,再一次设置每个顶点对应的过渡色。
增加文本的作用范围设置(单字/全文)
对于图片,整张图就是两个三角形网格,拼成一个矩形;而对于文本,每个字都是两个三角形网格,如果需要将过渡色作用于整行文本,则循环每个字的每个网格顶点,计算该顶点位于整个字符串中的位置进度,设置对应的过渡色插值结果。
- 由于文本可能存在换行,所以过渡色的计算,还需要考虑文本的行数,和每行的字符数。
- 如果使用了调整字间距的插件,还需要配合字间距的修改,重新计算网格偏移后的位置。