2018 年 3 月 30 日
Unity – 渐变文字
【实现】
[AddComponentMenu("UI/Effects/Gradient")]
public class Gradient : BaseMeshEffect
{
public enum Type
{
Horizontal,
Vertical,
}
public enum Blend
{
Override,
Add,
Multiply,
}
[SerializeField]
private Type m_GradientType = Type.Vertical;
[SerializeField]
private Blend m_BlendMode = Blend.Override;
[SerializeField]
[Range(-1, 1)]
private float m_Offset = 0;
[SerializeField]
private UnityEngine.Gradient m_effectGradient
= new UnityEngine.Gradient()
{
colorKeys = new GradientColorKey[] {
new GradientColorKey(Color.black, 0),
new GradientColorKey(Color.white, 1)}
};
private Text m_Text;
protected override void OnEnable()
{
m_Text = GetComponent<Text>();
}
public override void ModifyMesh(VertexHelper helper)
{
if (!IsActive() || helper.currentVertCount == 0)
return;
List<UIVertex> vertexList = new List<UIVertex>();
helper.GetUIVertexStream(vertexList);
int count = vertexList.Count;
switch (GradientType)
{
case Type.Horizontal:
float left = vertexList[0].position.x;
float right = vertexList[0].position.x;
float x = 0;
for (int i = count - 1; i >= 1; --i)
{
x = vertexList[i].position.x;
if (x > right)
right = x;
else if (x < left)
left = x;
}
float width = right - left;
UIVertex vertex = new UIVertex();
for (int i = 0; i < helper.currentVertCount; i++)
{
helper.PopulateUIVertex(ref vertex, i);
vertex.color = BlendColor(vertex.color,
EffectGradient.Evaluate((vertex.position.x - left) / width - Offset));
vertex.color.a = (byte)(m_Text.color.a * 255);
helper.SetUIVertex(vertex, i);
}
break;
case Type.Vertical:
float top = vertexList[0].position.y;
float bottom = vertexList[0].position.y;
float y = 0;
for (int i = count - 1; i >= 1; --i)
{
y = vertexList[i].position.y;
if (y > top)
top = y;
else if (y < bottom)
bottom = y;
}
float height = top - bottom;
UIVertex vertex2 = new UIVertex();
for (int i = 0; i < helper.currentVertCount; i++)
{
helper.PopulateUIVertex(ref vertex2, i);
vertex2.color = BlendColor(vertex2.color,
EffectGradient.Evaluate((vertex2.position.y - bottom) / height - Offset));
vertex2.color.a = (byte)(m_Text.color.a * 255);
helper.SetUIVertex(vertex2, i);
}
break;
}
}
Color BlendColor(Color colorA, Color colorB)
{
switch (BlendMode)
{
case Blend.Add:
return colorA + colorB;
case Blend.Multiply:
return colorA * colorB;
default:
return colorB;
}
}
}
【问题】
- 如果Text需要使用Outline和Shadow组件,需要将他们放在Gradient组件下面,否则上面两个组件的效果会被覆盖掉。
- 由于我给字体添加了DotweenAnimation组件用于制作Text的透明度动画,所以Gradient组件需要更新自己的透明度,与Text组件中的值统一。(蓝字部分)
【参考】