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

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

爬虫——有道云翻译

废话不多说直接上代码 固定文本内容 import timefrom selenium import webdriver from selenium.common.exceptions import NoSuchElementException, TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWai…

Python接口自动化测试:Json 数据处理实战

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 上一篇说了关于json数据处理&#xff0c;是为了断言方便&#xff0c;这篇就带各位小伙伴实战一下…

SpringBootWeb 篇-深入了解 AOP 面向切面编程与 AOP 记录操作日志案例

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 AOP 概述 1.1 构造简单 AOP 类 2.0 AOP 核心概念 2.1 AOP 执行流程 3.0 AOP 通知类型 4.0 AOP 通知顺序 4.1 默认按照切面类的类名字母排序 4.2 用 Order(数字) 注…

b端系统类管理平台设计前端开发案例

b端系统类管理平台设计前端开发案例

(学习笔记)数据基建-数据质量

数据基建-数据质量 数据质量数据质量保障措施如何推动上下游开展数据质量活动数据质量保障如何量化产出数据质量思考全链路数据质量保障项目 数据质量 概念&#xff1a;数据质量&#xff0c;意如其名&#xff0c;就是数据的准确性&#xff0c;他是数据仓库的基石&#xff0c;控…

【案例分享】印前制版工单系统:“鹿山科技”助力“铭匠数据”重塑业务流程

内容概要 本文介绍了鹿山信息科技通过明道云HAP平台的数字化解决方案提升了铭匠数据在印前制版行业的效率。周口铭匠数据科技有限公司位于河南省周口市沈丘县&#xff0c;是一家专注于印前制版设计服务的公司&#xff0c;成立于2023年。企业在销售业务、版材制作生产和美工设计…

CATIA入门操作案例——草图绘制案例,导入草图图片,尺寸约束直径/半径切换,草图分析闭合检查,草图固定

目录 引出草图绘制&#xff0c;导入图片方便绘制新建product&#xff0c;进入sketch tracer模块技巧&#xff1a;尺寸直径 / 半径切换技巧&#xff1a;右键&#xff0c;自动搜索 草图分析&#xff1a;检查闭合警告&#xff1a;Change it to material mode to see the Paintings…

60V大功率半桥GaN半桥驱动器替代LMG1210

1. 产品特性&#xff08;替代LMG1210&#xff09; ➢ 工作频率高达 10MHz ➢ 20ns 典型传播延迟 ➢ 5ns 高侧/低侧匹配 ➢ 两种输入控制模式 ➢ 具有可调死区时间的单个 PWM 输入、 独立输入模式 ➢ 1.5A 峰值拉电流和 3A 峰值灌电流 ➢ 内置 5V LDO ➢ 欠压保护 ➢ 过…

小程序简单版录音机

先来看看效果 结构 先来看看页面结构 <!-- wxml --><view class"wx-container"><view id"title">录音机</view><view id"time">{{hours}}:{{minute}}:{{second}}</view><view class"btngroup"…

【人工智能】第七部分:ChatGPT的未来展望

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

kafka安装流程

安装kafka前需要安装zookeeper zookeeper安装教程 1.新建一个logs文件夹 2.修改配置文件 3.修改listeners参数 4.以管理员身份启动kafka服务 .\bin\windows\kafka-server-start.bat .\config\server.properties 如果报 输入行太长。 命令语法不正确。 解决方案如下&#x…

基于工业互联网打造敏捷供应链的实现方式:创新路径与实践应用

引言 工业互联网和敏捷供应链是当今制造业发展中的两个重要概念。工业互联网以数字化、网络化和智能化为核心&#xff0c;致力于将传统工业生产与互联网技术相融合&#xff0c;从而实现生产过程的高效、智能和灵活。而敏捷供应链则强调快速响应市场需求、灵活调整生产和供应计划…

调用华为云实现人证核身证件版(二要素)

目录 1.作者介绍2.华为云人证核身2.1什么是人证核身2.2应用场景2.3限制要求 3.流程介绍3.1调用API实现3.2调用SDK实现 1.作者介绍 高凡平&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2023级研究生 研究方向&#xff1a;数码印花缺陷检测 电子邮件&#xf…

基于扩散动力学模型的乳腺癌在不完整DCE-MRI中的分割

文章目录 Diffusion Kinetic Model for Breast Cancer Segmentation in Incomplete DCE-MRI摘要方法实验结果 Diffusion Kinetic Model for Breast Cancer Segmentation in Incomplete DCE-MRI 摘要 针对现有方法需要完整时间序列数据(尤其是增强后图像)的问题,DKM仅利用预增…

wordpress里面嵌入哔哩哔哩视频的方法

我们正常如果从blibli获取视频分享链接然后在wordpress里面视频URL插入&#xff0c;发现是播放不了的 而视频嵌入代码直接粘贴呢窗口又非常的小 非常的难受&#xff0c;就需要更改一下代码。你可以在在allowfullscreen"true"的后面&#xff0c;留1个空格&#xff…

掌控数据流:深入解析 Java Stream 编程

Java 8 引入了一种新的抽象称为流&#xff08;Stream&#xff09;&#xff0c;它可以让你以一种声明的方式处理数据。Java 8 Stream API 可以极大提高 Java 程序员的生产力&#xff0c;使代码更简洁&#xff0c;更易读&#xff0c;并利用多核架构进行外部迭代。这里将详细介绍 …

Python Flask实现蓝图Blueprint配置和模块渲染

Python基础学习&#xff1a; Pyhton 语法基础Python 变量Python控制流Python 函数与类Python Exception处理Python 文件操作Python 日期与时间Python Socket的使用Python 模块Python 魔法方法与属性 Flask基础学习&#xff1a; Python中如何选择Web开发框架&#xff1f;Pyth…

SQLserver通过CLR调用TCP接口

一、SQLserver启用CLR 查看是否开启CRL&#xff0c;如果run_value1&#xff0c;则表示开启 EXEC sp_configure clr enabled; GO RECONFIGURE; GO如果未启用&#xff0c;则执行如下命令启用CLR sp_configure clr enabled, 1; GO RECONFIGURE; GO二、创建 CLR 程序集 创建新项…

【算法】深入浅出爬山算法:原理、实现与应用

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

简单聊下办公白环境

在当今信息化时代&#xff0c;办公环境对于工作效率和员工满意度有着至关重要的影响。而白名单作为一种网络安全策略&#xff0c;其是否适合办公环境&#xff0c;成为了许多企业和组织需要思考的问题。本文将从白名单的定义、特点及其在办公环境中的应用等方面&#xff0c;探讨…