- 前言
- 【Unity实战篇 】 | Unity实现UGUI颜色渐变,支持透明渐变
- 一、双层颜色渐变
- 1.1 组件属性面板
- 1.2 效果及代码
- 二、多层颜色渐变
- 2.1 组件属性面板
- 2.2 效果及代码
- 总结
前言
- 在Unity中UGUI的实现图片和文字颜色渐变效果是一个很常见的需求。
- 下面就来看一下颜色渐变效果是怎样实现的吧。
【Unity实战篇 】 | Unity实现UGUI颜色渐变,支持透明渐变
效果 | 展示 |
---|---|
一、双层颜色渐变
双层颜色渐变 是游戏中用到的比较多的效果,实现方式也比较简单,下面看下效果和实现方式。
1.1 组件属性面板
属性 | 说明 |
---|---|
Direction | 方向 |
Color1 | 颜色1 |
Color2 | 颜色2 |
range | 偏移量 |
isFlip | 是否翻转 |
通过配置参数可以调节渐变的颜色、偏移量和翻转效果。
1.2 效果及代码
完整代码如下:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class Gradient : BaseMeshEffect
{public enum DirectionType{Horizontal,Vertical,}[SerializeField]private DirectionType m_Direction = DirectionType.Vertical;[SerializeField]public Color32 m_Color1 = Color.white;[SerializeField]public Color32 m_Color2 = Color.white;[SerializeField]private float m_Range = 0f;[SerializeField]private bool m_Flip = false;public override void ModifyMesh(VertexHelper vh){if (!IsActive() || vh.currentVertCount <= 0){return;}int count = vh.currentVertCount;List<UIVertex> vertices = new List<UIVertex>();for (int i = 0; i < count; i++){UIVertex uIVertex = new UIVertex();vh.PopulateUIVertex(ref uIVertex, i);vertices.Add(uIVertex);}switch (m_Direction){case DirectionType.Horizontal:DrawHorizontal(vh, vertices, count);break;case DirectionType.Vertical:DrawVertical(vh, vertices, count);break;default:break;}}private void DrawVertical(VertexHelper vh, List<UIVertex> vertices, int count){float topY = vertices[0].position.y;float bottomY = vertices[0].position.y;for (int i = 0; i < count; i++){float y = vertices[i].position.y;if (y > topY){topY = y;}else if (y < bottomY){bottomY = y;}}float height = topY - bottomY;for (int i = 0; i < count; i++){UIVertex vertex = vertices[i];Color32 color = Color.white;if (m_Flip){color = Color32.Lerp(m_Color2, m_Color1, 1 - (vertex.position.y - bottomY) / height * (1f - m_Range));}else{color = Color32.Lerp(m_Color2, m_Color1, (vertex.position.y - bottomY) / height * (1f - m_Range));}vertex.color = color;vh.SetUIVertex(vertex, i);}}private void DrawHorizontal(VertexHelper vh, List<UIVertex> vertices, int count){float topX = vertices[0].position.x;float bottomX = vertices[0].position.x;for (int i = 0; i < count; i++){float y = vertices[i].position.x;if (y > topX){topX = y;}else if (y < bottomX){bottomX = y;}}float height = topX - bottomX;for (int i = 0; i < count; i++){UIVertex vertex = vertices[i];Color32 color = Color.white;if (m_Flip){color = Color32.Lerp(m_Color1, m_Color2, 1 - (vertex.position.x - bottomX) / height * (1f - m_Range));}else{color = Color32.Lerp(m_Color1, m_Color2, (vertex.position.x - bottomX) / height * (1f - m_Range));}vertex.color = color;vh.SetUIVertex(vertex, i);}}
}
使用ModifyMesh()方法
(通常在实现IMeshModifier接口
时被重写,这个接口允许开发者自定义UI元素在渲染时的外观)进行网格修改。
比如垂直渐变时,找到图形的顶部和底部顶点并计算出高度差,然后计算出所有顶点位置的颜色值,并根据设置好的颜色进行赋值即可完成颜色渐变效果。
二、多层颜色渐变
在有些情况下双层渐变可能满足不了需求,需要用到多层颜色渐变的效果。
2.1 组件属性面板
属性 | 说明 |
---|---|
Direction | 方向 |
ColorArray | 颜色数组 |
Flip | 是否翻转 |
2.2 效果及代码
完整代码如下:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class Gradients : BaseMeshEffect
{/// <summary>/// 渐变方向/// </summary>public enum DirectionType{Horizontal,Vertical,}[SerializeField]private DirectionType direction = DirectionType.Horizontal;[SerializeField]private Color32[] m_ColorArray = new Color32[2] { Color.black, Color.white };[SerializeField]private bool m_Flip = false;//每一个文字的顶点数int m_VertexCountPer = 6;//顶点缓存List<UIVertex> m_VertexCache = new List<UIVertex>();//绘制使用的顶点列表List<UIVertex> m_VertexList = new List<UIVertex>();public override void ModifyMesh(VertexHelper vh){if (!IsActive() || m_ColorArray.Length < 2) { return; }vh.GetUIVertexStream(m_VertexCache);if (m_VertexCache.Count == 0) { return; }switch (direction){case DirectionType.Horizontal:ApplyGradient_Horizontal(m_VertexCache, m_ColorArray.Length);break;case DirectionType.Vertical:ApplyGradient_Vertical(m_VertexCache, m_ColorArray.Length);break;default:break;}vh.Clear();vh.AddUIVertexTriangleStream(m_VertexList);m_VertexCache.Clear();m_VertexList.Clear();}void ApplyGradient_Horizontal(List<UIVertex> vertexCache, int colorCount){for (int n = 0; n < m_VertexCache.Count / 6; n++){UIVertex lastVertexLT = new UIVertex();UIVertex lastVertexLB = new UIVertex();UIVertex lastVertexRT = new UIVertex();UIVertex lastVertexRB = new UIVertex();for (int i = 0; i < colorCount - 1; i++){UIVertex vertexRT;UIVertex vertexLT;UIVertex vertexRB;UIVertex vertexLB;//翻转if (m_Flip){//右上角和右下角if (i == 0){vertexRT = CalcVertex(vertexCache[n * m_VertexCountPer + 1], m_ColorArray[i]);vertexRB = CalcVertex(vertexCache[n * m_VertexCountPer + 2], m_ColorArray[i]);}else{vertexRT = lastVertexLT;vertexRB = lastVertexLB;}//左上角和左下角if (i == colorCount - 2){vertexLT = CalcVertex(vertexCache[n * m_VertexCountPer + 0], m_ColorArray[i + 1]);vertexLB = CalcVertex(vertexCache[n * m_VertexCountPer + 4], m_ColorArray[i + 1]);}else{vertexLT = CalcVertex(vertexCache[n * m_VertexCountPer + 0], vertexCache[n * m_VertexCountPer + 1],(colorCount - i - 2) * 1f / (colorCount - 1), m_ColorArray[i + 1]);vertexLB = CalcVertex(vertexCache[n * m_VertexCountPer + 4], vertexCache[n * m_VertexCountPer + 2],(colorCount - i - 2) * 1f / (colorCount - 1), m_ColorArray[i + 1]);}lastVertexLT = vertexLT;lastVertexLB = vertexLB;}else{//左上角和左下角if (i == 0){vertexLT = CalcVertex(vertexCache[n * m_VertexCountPer + 0], m_ColorArray[i]);vertexLB = CalcVertex(vertexCache[n * m_VertexCountPer + 4], m_ColorArray[i]);}else{vertexLT = lastVertexRT;vertexLB = lastVertexRB;}//右上角和右下角if (i == colorCount - 2){vertexRT = CalcVertex(vertexCache[n * m_VertexCountPer + 1], m_ColorArray[i + 1]);vertexRB = CalcVertex(vertexCache[n * m_VertexCountPer + 2], m_ColorArray[i + 1]);}else{vertexRT = CalcVertex(vertexCache[n * m_VertexCountPer + 1], vertexCache[n * m_VertexCountPer + 0],(colorCount - i - 2) * 1f / (colorCount - 1), m_ColorArray[i + 1]);vertexRB = CalcVertex(vertexCache[n * m_VertexCountPer + 2], vertexCache[n * m_VertexCountPer + 4],(colorCount - i - 2) * 1f / (colorCount - 1), m_ColorArray[i + 1]);}lastVertexRT = vertexRT;lastVertexRB = vertexRB;}m_VertexList.Add(vertexLT);m_VertexList.Add(vertexRT);m_VertexList.Add(vertexRB);m_VertexList.Add(vertexRB);m_VertexList.Add(vertexLB);m_VertexList.Add(vertexLT);}}}void ApplyGradient_Vertical(List<UIVertex> vertexCache, int colorCount){for (int n = 0; n < m_VertexCache.Count / 6; n++){UIVertex lastVertexLT = new UIVertex();UIVertex lastVertexRT = new UIVertex();UIVertex lastVertexLB = new UIVertex();UIVertex lastVertexRB = new UIVertex();for (int i = 0; i < colorCount - 1; i++){UIVertex vertexRT;UIVertex vertexLT;UIVertex vertexRB;UIVertex vertexLB;//翻转if (m_Flip){//左下角和右下角if (i == 0){vertexLB = CalcVertex(vertexCache[n * m_VertexCountPer + 4], m_ColorArray[i]);vertexRB = CalcVertex(vertexCache[n * m_VertexCountPer + 2], m_ColorArray[i]);}else{vertexLB = lastVertexLT;vertexRB = lastVertexRT;}//左上角和右上角if (i == colorCount - 2){vertexLT = CalcVertex(vertexCache[n * m_VertexCountPer + 0], m_ColorArray[i + 1]);vertexRT = CalcVertex(vertexCache[n * m_VertexCountPer + 1], m_ColorArray[i + 1]);}else{vertexLT = CalcVertex(vertexCache[n * m_VertexCountPer + 0], vertexCache[n * m_VertexCountPer + 4],(colorCount - i - 2) * 1f / (colorCount - 1), m_ColorArray[i + 1]);vertexRT = CalcVertex(vertexCache[n * m_VertexCountPer + 1], vertexCache[n * m_VertexCountPer + 2],(colorCount - i - 2) * 1f / (colorCount - 1), m_ColorArray[i + 1]);}lastVertexLT = vertexLT;lastVertexRT = vertexRT;}else{//左上角和右上角if (i == 0){vertexLT = CalcVertex(vertexCache[n * m_VertexCountPer + 0], m_ColorArray[i]);vertexRT = CalcVertex(vertexCache[n * m_VertexCountPer + 1], m_ColorArray[i]);}else{vertexLT = lastVertexLB;vertexRT = lastVertexRB;}//左下角和右下角if (i == colorCount - 2){vertexLB = CalcVertex(vertexCache[n * m_VertexCountPer + 4], m_ColorArray[i + 1]);vertexRB = CalcVertex(vertexCache[n * m_VertexCountPer + 2], m_ColorArray[i + 1]);}else{vertexLB = CalcVertex(vertexCache[n * m_VertexCountPer + 4], vertexCache[n * m_VertexCountPer + 0],(colorCount - i - 2) * 1f / (colorCount - 1), m_ColorArray[i + 1]);vertexRB = CalcVertex(vertexCache[n * m_VertexCountPer + 2], vertexCache[n * m_VertexCountPer + 1],(colorCount - i - 2) * 1f / (colorCount - 1), m_ColorArray[i + 1]);}lastVertexLB = vertexLB;lastVertexRB = vertexRB;}m_VertexList.Add(vertexLT);m_VertexList.Add(vertexRT);m_VertexList.Add(vertexRB);m_VertexList.Add(vertexRB);m_VertexList.Add(vertexLB);m_VertexList.Add(vertexLT);}}}/// <summary>/// 计算顶点数据(只计算颜色)/// </summary>UIVertex CalcVertex(UIVertex vertex, Color32 color){vertex.color = color;return vertex;}/// <summary>/// 计算顶点数据/// </summary>UIVertex CalcVertex(UIVertex vertexA, UIVertex vertexB, float ratio, Color32 color){UIVertex vertexTemp = new UIVertex();vertexTemp.position = (vertexB.position - vertexA.position) * ratio + vertexA.position;vertexTemp.color = color;vertexTemp.normal = (vertexB.normal - vertexA.normal) * ratio + vertexA.normal;vertexTemp.tangent = (vertexB.tangent - vertexA.tangent) * ratio + vertexA.tangent;vertexTemp.uv0 = (vertexB.uv0 - vertexA.uv0) * ratio + vertexA.uv0;vertexTemp.uv1 = (vertexB.uv1 - vertexA.uv1) * ratio + vertexA.uv1;return vertexTemp;}
}
使用时将该渐变脚本挂载到Image或者Text组件上,然后配置自己所需的参数即可。
总结
- 本文提供了两种UGUI颜色渐变的方法,可以满足多数使用情景。
- 如果有更好的解决方案,也可以在评论区指出一起分享学习!
🎬 博客主页:https://xiaoy.blog.csdn.net
🎥 本文由 呆呆敲代码的小Y 原创 🙉
🎄 学习专栏推荐:Unity系统学习专栏
🌲 游戏制作专栏推荐:游戏制作
🌲Unity实战100例专栏推荐:Unity 实战100例 教程
🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
📆 未来很长,值得我们全力奔赴更美好的生活✨
------------------❤️分割线❤️-------------------------
资料白嫖,技术互助
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
🧡 Unity系统学习专栏 🧡 | 入门级 | 本专栏从Unity入门开始学习,快速达到Unity的入门水平 |
💛 Unity实战类项目 💛 | 进阶级 | 计划制作Unity的 100个实战案例!助你进入Unity世界,争取做最全的Unity原创博客大全。 |
❤️ 游戏制作专栏 ❤️ | 难度偏高 | 分享学习一些Unity成品的游戏Demo和其他语言的小游戏! |
💚 游戏爱好者万人社区💚 | 互助/吹水 | 数万人游戏爱好者社区,聊天互助,白嫖奖品 |
💙 Unity100个实用技能💙 | Unity查漏补缺 | 针对一些Unity中经常用到的一些小知识和技能进行学习介绍,核心目的就是让我们能够快速学习Unity的知识以达到查漏补缺 |