【Unity实战篇 】 | Unity实现UGUI颜色渐变,支持透明渐变

请添加图片描述

      • 前言
  • 【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的知识以达到查漏补缺

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/22023.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习中的集成学习

&#x1f4ac;内容概要 1 集成学习概述及主要研究领域 2 简单集成技术  2.1 投票法  2.2 平均法  2.3 加权平均 3 高级集成技术  3.1 Bagging  3.2 Boosting  3.3 Bagging vs Boosting 4 基于Bagging和Boosting的机器学习算法  4.1 sklearn中的Bagging算法  4.2 sklea…

python 深浅拷贝

浅拷贝 copy函数就是浅拷贝 copy函数是浅拷贝&#xff0c;只对可变类型的第一层对象进行拷贝 对拷贝的对象开辟新的内存空间进行存储&#xff0c;子对象不会开辟新的空间 list1 [1, 2, 3] list2 [a, list1] list3 list2.copy()print(id(list1)) print(id(list2)) …

Layout软件AD中关于铺铜的技巧

Layout软件AD中关于铺铜的技巧 目录 一.铜的连接方式: 二.关于铜的编辑: 三.Shelve的使用:

探索Linux世界的钥匙:Bash命令详解

标题&#xff1a;探索Linux世界的钥匙&#xff1a;Bash命令详解 引言&#xff1a; 在Linux的世界里&#xff0c;Bash&#xff08;Bourne Again Shell&#xff09;无疑是每个用户和系统管理员的得力助手。作为Linux系统中最常用的shell之一&#xff0c;Bash提供了丰富的命令和强…

1961. 检查字符串是否为数组前缀 - 力扣

1. 题目 给你一个字符串 s 和一个字符串数组 words &#xff0c;请你判断 s 是否为 words 的 前缀字符串 。 字符串 s 要成为 words 的 前缀字符串 &#xff0c;需要满足&#xff1a;s 可以由 words 中的前 k&#xff08;k 为 正数 &#xff09;个字符串按顺序相连得到&#xf…

大型语言模型的工作原理(LLM:从零学起)

目录 一、说明 二、LLM如何运作 三、预训练&#xff1a;基本模型 四、微调&#xff1a;培训助手 五、RLHF&#xff1a;从人类反馈中强化学习 六、提示工程 七、总结 一、说明 这是我们谈论LLM系列的第二篇文章。在本文中&#xff0c;我们旨在为大型语言模型 &#xff08;LLM&am…

Feign @SpringQueryMap将POJO或Map参数注释为查询参数映射

一、 Feign SpringQueryMap支持 OpenFeign QueryMap批注支持将POJO用作GET参数映射。不幸的是&#xff0c;默认的OpenFeign QueryMap注释与Spring不兼容&#xff0c;因为它缺少value属性。 Spring Cloud OpenFeign提供等效的SpringQueryMap批注&#xff0c;该批注用于将POJO或…

企业微信hook接口协议,ipad协议http,chatid转群id

chatid转群id 参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信 请求示例 {"uuid":"3240fde0-45e2-48c0-90e8-cb098d0ebe43","chatid":"wrO9o4EAAAeR_nSlmjeX1RWrKAKxN8jQ" } 返回示例 {&…

Flutter 中的 PrimaryScrollController 小部件:全面指南

Flutter 中的 PrimaryScrollController 小部件&#xff1a;全面指南 Flutter 是一个由 Google 开发的跨平台 UI 框架&#xff0c;它允许开发者使用 Dart 语言构建高性能、美观的移动、Web 和桌面应用。在 Flutter 的滚动机制中&#xff0c;PrimaryScrollController 起着至关重…

【银河麒麟V10服务器OS-系统根分区扩容】指导教程手册

【银河麒麟V10服务器OS-系统根分区扩容】指导教程手册 环境信息&#xff1a;VMware虚拟软件16.0 首先查看KylinOS服务器版本&#xff1a;nkvers 备注&#xff1a; (Tercel) 版本是 V10 SP1 版本&#xff0c; (Sword) 版本是 V10 SP2 版本&#xff0c; (Lance) 版本是 V10 …

UE4 使用样条线做鱼儿封闭路径动画

描述&#xff1a;鱼儿的游动动画的特点 1.通常是始终保持Y (Pitch)轴角度不变 2.调头的时候改变的是Z轴角度 效果&#xff1a;调头的时候比较自然 蓝图&#xff1a; 最后为了让鱼儿有恒定的游动速度&#xff0c;增加以下蓝图节点&#xff0c;游动速度为50

CTFHUB-技能树-web-web前置技能-HTTP协议全

目录 1.请求方式 2.302跳转 3.Cookie 4.基础认证 5.响应包源码 1.请求方式 curl -v -X http://challenge-3022c877a8dcedeb.sandbox.ctfhub.com:10800/index.php 2.302跳转 参考链接&#xff1a;http://t.csdnimg.cn/aqdNG 301——永久性重定向。该状态码表示请求的资源已…

Avue-data数据大屏显示柱状图(附Demo讲解)

目录 前言1. 接口方式2. SQL查询 前言 由于网上对这部分的知识点相对较少&#xff0c;研究半天的框架最终输出结果 此文主要以记录总结的方式展示如何使用数据库以及接口方式 需要明白柱状图的返回数据格式&#xff1a; #柱状图数据格式 {"categories": ["苹…

【redis】Spring之RedisTemplate配置与使用

1.概述 转载&#xff1a;Spring之RedisTemplate配置与使用 用过redis&#xff0c;但直接使用Jedis进行相应的交互操作&#xff0c;现在正好来看一下RedisTemplate是怎么实现的&#xff0c;以及使用起来是否更加便利 2. 基本配置 2.1. 依赖 依然是采用Jedis进行连接池管理&…

C# 接口的使用案例

IEnumerable接口的使用案例 1. IEnumerable接口同时满足数组和列表2. OPPO和VIVO使用相同接口 1. IEnumerable接口同时满足数组和列表 利用 IEnumerable 这个接口来实现一个方法可以同时满足数组和列表传入。接口就是供需双方的约定/契约&#xff0c;需求方是用户需要计算一组…

组织是什么,为什么需要组织,为什么需要公司

垂直组织 组织架构设计&#xff0c;曾经咱们多个章节进行沟通&#xff0c;今天再回到组织本身。不妨可以思考一个这样的问题&#xff0c;或者随访身边的老板或者朋友&#xff0c;让他们绘制一个组织架构图&#xff0c;或者绘制一个本组织一个视图&#xff0c;得到以下图的示意…

TypeScript中的迭代器和生成器:控制数据流的新方法

引言 迭代器和生成器是ES6及更高版本JavaScript中引入的两个强大的迭代协议&#xff0c;它们提供了一种新的方式来遍历数据集合和控制函数的执行流程。TypeScript通过类型系统增强了这些特性&#xff0c;使得迭代更加安全和灵活。 基础知识 迭代器&#xff08;Iterator&…

vue从入门到精通(六):数据代理

一&#xff0c;什么是数据代理 通过一个对象代理对另一个对象中属性的操作 二&#xff0c;object.defineproperty方法 object.defineproperty方法可以对对象追加属性 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>object…

[Redis]Set类型

集合类型也是保存多个字符串类型的元素的&#xff0c;但和列表类型不同的是&#xff0c;集合中 1&#xff09;元素之间是无序的 2&#xff09;元素不允许重复 一个集合中最多可以存储2^32-1个元素。 Redis 除了支持集合内的增删查改操作&#xff0c;同时还支持多个集合取交…

【数据结构】链表----头结点的作用

链表是一种常见的数据结构&#xff0c;由一系列节点&#xff08;Node&#xff09;组成&#xff0c;每个节点包含数据和指向下一个节点的指针。链表的头结点&#xff08;Head Node&#xff09;也称为哨兵位&#xff0c;是链表的起点&#xff0c;通常有以下几个重要作用&#xff…