Unity扩展 Text 彩虹文本

news2024/12/22 20:26:29

本文章用于原生组件 Text 的扩展 TextRainbow,对于新版TextMeshPro不适用。

一、效果预览图:

默认:

随机:

循环:

二、原理

通过强制刷新顶点数据,来修改颜色。

通过Unity中自带的 BaseMeshEffect 抽象类,可以直接修改UI元素的网格,从而达到比如阴影,描边,UV顶点颜色等视觉效果。

新建一个脚本继承 BaseMeshEffect 抽象类,通过 ModifyMesh 方法来自定义想要的效果。 ModifyMesh 方法中自带参数类型 VertexHelper,通过参数类型中提供的 GetUIVertexStream、PopulateUIVertex 和 SetUIVertex 方法来获取当前网格的顶点数据并重新设置回去。

彩虹颜色的方式有很多种,这里推荐使用渐变 Gradient 去做比较方便。Gradient 的颜色设置和获取在代码中已有展示,没啥好说的。

对于颜色的显示三种方式,循环模式是通过Update方法驱动渐变颜色索引实现的,并且添加是否忽略引擎的TimeScale影响。

三、代码

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Random = UnityEngine.Random;
[RequireComponent(typeof(Text))]
public class TextRainbow : BaseMeshEffect
{
    public enum VerticesColorType
    {
        None,
        Random,
        Loop
    }
    [SerializeField] protected Text target;
    /// <summary>
    /// 彩虹条
    /// </summary>
    public Gradient gradient = new();
    /// <summary>
    /// 彩虹条颜色数量
    /// </summary>
    private int ColorCount => gradient.colorKeys.Length;
    /// <summary>
    /// 当前索引下标 0 ~ gradientColors
    /// </summary>
    private int _index = 0;
    /// <summary>
    /// 进度,0 ~ 1
    /// </summary>
    private float _timeProcess = 0;
    private bool _openRainbow = false;
    /// <summary>
    /// 存在彩虹文本
    /// </summary>
    private bool _haveRainbow = false;
    private readonly List<UIVertex> _vertices = new();
    /// <summary>
    /// 滚动速度
    /// </summary>
    public float ScrollSpeed = 3f;
    /// <summary>
    /// 打开彩虹
    /// </summary>
    public bool OpenRainbow
    {
        get => _openRainbow;
        set
        {
            if (_openRainbow == value)
            {
                return;
            }
            _openRainbow = value;
            UpdateIndex();
            HaveRainbowCondition();
            target.SetVerticesDirty();
        }
    }
    /// <summary>
    /// 彩虹颜色类型
    /// </summary>
    private VerticesColorType _colorType = VerticesColorType.None;
    public VerticesColorType ColorType
    {
        get => _colorType;
        set
        {
            if (_colorType == value)
            {
                return;
            }
            _colorType = value;
            UpdateIndex();
            if (_openRainbow)
            {
                target.SetVerticesDirty();
            }
        }
    }
    /// <summary>
    /// 忽略时间缩放
    /// </summary>
    public bool unScaledTime = false;
    public string Text
    {
        get => target.text;
        set => SetText(value);
    }
    protected override void Awake()
    {
        _index = 0;
        if (!target)
        {
            target = GetComponent<Text>();
        }
    }
    private void Update()
    {
        if (!OpenRainbow)
        {
            return;
        }
        if (!_haveRainbow)
        {
            return;
        }
        if (_colorType != VerticesColorType.Loop) return;
        _timeProcess += (unScaledTime ? Time.unscaledDeltaTime : Time.deltaTime) * ScrollSpeed;
        if (!(_timeProcess >= 1)) return;
        _timeProcess -= 1;
        _index++;
        target.SetVerticesDirty();
        if (_index >= ColorCount)
        {
            _index = 0;
        }
    }
#if UNITY_EDITOR
    protected override void Reset()
    {
        base.Reset();
        target = GetComponent<Text>();
    }
#endif
    public override void ModifyMesh(VertexHelper vh)
    {
        if (!_haveRainbow)
        {
            return;
        }
        if (!IsActive() || vh.currentIndexCount == 0)
        {
            return;
        }
        _vertices.Clear();
        vh.GetUIVertexStream(_vertices);
        UIVertex uiVertex = new();
        for (var i = 0; i < vh.currentVertCount; ++i)
        {
            vh.PopulateUIVertex(ref uiVertex, i);
            uiVertex.color = CalcColor(i);
            vh.SetUIVertex(uiVertex, i);
        }
    }
    private Color CalcColor(int index)
    {
        if (!OpenRainbow)
        {
            return target.color;
        }
        index /= 4;
        index += _index;
        if (index >= ColorCount)
        {
            index %= ColorCount;
        }

        return gradient.Evaluate(gradient.colorKeys[index].time);
    }
    private void SetText(string text)
    {
        if (string.IsNullOrEmpty(text))
        {
            _haveRainbow = false;
            target.text = string.Empty;
            return;
        }
        _haveRainbow = OpenRainbow;
        target.text = text;
    }
    private void HaveRainbowCondition()
    {
        if (string.IsNullOrEmpty(Text))
        {
            _haveRainbow = false;
            return;
        }
        _haveRainbow = OpenRainbow;
    }
    private void UpdateIndex()
    {
        switch (_colorType)
        {
            case VerticesColorType.Random:
                _index = Random.Range(0, ColorCount);
                break;
            case VerticesColorType.None:
            case VerticesColorType.Loop:
            default:
                _index = 0;
                break;
        }
    }
}

 面板扩展:

using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(TextRainbow), true)]
[CanEditMultipleObjects]
public class TextRainbowEditor : Editor
{
    private const int NumberOfColors = 7;
    private TextRainbow Target => (TextRainbow)target;
    private SerializedProperty _component;
    private SerializedProperty _unScaledTime;
    protected void OnEnable()
    {
        _component = serializedObject.FindProperty("target");
        _unScaledTime = serializedObject.FindProperty("unScaledTime");
    }
    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        GUI.enabled = false;
        EditorGUILayout.PropertyField(_component);
        GUI.enabled = true;
        EditorGUI.BeginChangeCheck();
        #region Gradient
        EditorGUILayout.BeginHorizontal();
        Target.gradient = EditorGUILayout.GradientField("Gradient", Target.gradient);
        // 预设彩虹渐变
        if (GUILayout.Button("Rainbow", GUILayout.Width(80)))
        {
            DrawRainbowGradient();
        }
        EditorGUILayout.EndHorizontal();
        #endregion
        Target.ColorType = (TextRainbow.VerticesColorType)EditorGUILayout.EnumPopup("Color Type", Target.ColorType);
        Target.ScrollSpeed = EditorGUILayout.Slider("Scroll Speed", Target.ScrollSpeed, 0, 10);
        Target.OpenRainbow = EditorGUILayout.Toggle("Open Rainbow", Target.OpenRainbow);
        EditorGUILayout.PropertyField(_unScaledTime);
        EditorGUILayout.LabelField("Text");
        Target.Text = EditorGUILayout.TextArea(Target.Text, GUILayout.MinHeight(EditorGUIUtility.singleLineHeight * 3));
        if (EditorGUI.EndChangeCheck())
        {
            EditorUtility.SetDirty(Target);
        }
        serializedObject.ApplyModifiedProperties();
    }
    
    // 预设彩虹渐变
    private void DrawRainbowGradient()
    {
        var colorKeys = new GradientColorKey[NumberOfColors];
        for (var i = 0; i < NumberOfColors; i++)
        {
            float dividend = NumberOfColors - 1;
            var index = i;
            if (i == 1)
            {
                dividend = 12f;
            }
            else if (i > 1)
            {
                index = i - 1;
            }
            colorKeys[i].color = Color.HSVToRGB(index / dividend, 1f, 1f);
            colorKeys[i].time = (float)i / (NumberOfColors - 1);
        }
        Target.gradient.colorKeys = colorKeys;
        Target.gradient.alphaKeys = new[]
        {
            new GradientAlphaKey(1, 0),
            new GradientAlphaKey(1, 1)
        };
    }
}

写出来后稍加整理就发出来了,如果有更优解(原生组件扩展)欢迎指教。

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

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

相关文章

五、OpenCVSharp 中的图像滤波与平滑

文章目录 简介一、均值滤波1. 原理和数学公式2. 不同大小的滤波核效果对比3. 边界处理方式二、高斯滤波1. 高斯核的生成2. 标准差对滤波效果的影响3. 高斯滤波的应用场景(如去除高斯噪声)三、中值滤波1. 中值的计算方法2. 中值滤波对椒盐噪声的处理效果3. 中值滤波的性能分析…

AWS Lambda 十年回顾:功能总览、更新记录与入门指南

这次&#xff0c;我为2014年11月发布的AWS Lambda创建了一个历史时间表。AWS Lambda 是一项无服务器、全托管的代码执行服务&#xff0c;今年2024年11月将迎来其宣布发布的十周年纪念。虽然提前了一些&#xff0c;但为了提前庆祝这一重要时刻&#xff0c;我写了这篇文章。 文章…

空间间隔组(Spacers)-Qt-思维导图-学习笔记

空间间隔组&#xff08;Spacers&#xff09; 空间间隔组&#xff08;Spacers&#xff09; &#xff08;1&#xff09;Horizontal Spacer:水平间隔 &#xff08;2&#xff09;Vertical Spacer:垂直间隔 QSpacerItem 控件简介 继承关系&#xff1a;QSpacerItem 继承自 QLayou…

面试必备之——TCP/UDP(二)

TCP流量控制 让发送方发送的速率不要太快&#xff0c;要让接收方开的及接收&#xff0c;防止发送方发送太快&#xff0c;导致接收方来不及接收。是端到端之间的控制 滑动窗口是实现流量控制的方法之一 TCP流量控制-滑动窗口 滑动窗口是传输层进行流控的一种措施&#xff0c;…

电脑版视频剪辑软件哪个好?适合新手使用的剪辑软件!

电脑版视频剪辑软件哪个好&#xff1f;在电脑版视频剪辑软件的选择上&#xff0c;每位用户都有其独特的偏好和需求。对于初学者而言&#xff0c;寻找一款操作简便、功能齐全的软件至关重要。为大家推荐几款常用的视频剪辑软件&#xff1a; 1、福昕视频剪辑 2、HitFilm 3、DaVin…

天了噜,IDEA竟然还有这种坑!

问题描述 IDEA 编辑器 idea Cannot resolve symbol 鼠标聚焦时&#xff0c;错误信息为&#xff1a;” idea Cannot resolve symbol “ IDEA自动修复功能 提示信息如下&#xff0c;然而并没有什么卵用。 问题梳理&#xff1a; IDEA 这个目录下的包都引入不了 import org.s…

Redis的分布式部署方案-哨兵

Redis 的主从复制模式下&#xff0c;⼀旦主节点由于故障不能提供服务&#xff0c;需要⼈⼯进⾏主从切换&#xff0c;同时⼤量 的客⼾端需要被通知切换到新的主节点上&#xff0c;对于上了⼀定规模的应⽤来说&#xff0c;这种⽅案是⽆法接受的&#xff0c; 于是 Redis 从 2.8 开…

uniapp加载第三方字体方案对比(附原生微信小程序方案)

文章目录 官方文档uniapp文档微信小程序文档 下载字体包引入方案限制微信小程序限制uniapp的限制 方案对比方案1&#xff1a;CSS本地加载方案2&#xff1a;CSS远程加载方案3&#xff1a;转换为base64&#xff0c;然后通过css引入方案4&#xff1a;使用uni.loadFontFace() 页面使…

手撕初阶数据结构之---排序

1.排序概念及运用 排序&#xff1a;所谓排序&#xff0c;就是使⼀串记录&#xff0c;按照其中的某个或某些关键字的⼤⼩&#xff0c;递增或递减的排列起来的操作。 常见的排序算法 直接插入排序的时间复杂度是O(N^2) 这个是最差的情况下&#xff0c;就是大的在前面&#xff…

30kw 可调恒流电子负载,你了解多少?

30kW可调恒流电子负载&#xff0c;是一种用于测试电源、蓄电池、发电机等电力设备的设备。它的主要功能是模拟实际负载&#xff0c;通过调节电流的大小&#xff0c;来检测电力设备的工作性能和稳定性。 让我们了解一下什么是电子负载。电子负载是一种可以吸收或提供电能的设备&…

【数据分析---偏企业】 Excel操作

各位大佬好 &#xff0c;这里是阿川的博客&#xff0c;祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 Excel操作前 必看 Python 初阶 Python—语言基础与…

[MRCTF2020]套娃 php字符串解析绕过,jsfuck编码

进来看到代码 <!-- //1st $query $_SERVER[QUERY_STRING];if( substr_count($query, _) ! 0 || substr_count($query, %5f) ! 0 ){die(Y0u are So cutE!); }if($_GET[b_u_p_t] ! 23333 && preg_match(/^23333$/, $_GET[b_u_p_t])){echo "you are going to th…

超维室外轮式巡检机器人打造无人值守变电站

变电站是电力系统的重要组成部分&#xff0c;负责电能的转换、分配和传输&#xff0c;确保电力供应的稳定性和安全性。然而&#xff0c;由于变电站内设备众多、环境复杂、风险较高&#xff0c;传统的人工巡检方式面临着效率低下、成本高昂和人员安全隐患等问题。为应对这些挑战…

苹果iOS 18 Beta 6更新亮点一览:这些新功能让你爱不释手

苹果公司作为全球科技行业的领军者&#xff0c;每一次的系统更新都备受业界和消费者的关注。 iOS系统作为苹果设备的核心&#xff0c;其每一次迭代都带来了新功能和优化&#xff0c;极大地提升了用户体验。2024年8月13日&#xff0c;苹果向iPhone用户推送了iOS 18 Beta 6更新&…

水印去除方法

有一批建筑图去水印&#xff0c;水印的位置基本位于左右下角或者图片中间&#xff0c;因此调研一些去水印的方法&#xff0c;以前做电商图场景的水印去除或者印章去除的话&#xff0c;通常会训练一个unet来做这个事情。 1.工具 3 秒去水印&#xff01;6 款超好用的免费图像去…

Endnote与word关联 解决方案: COM加载项-----》CWYW插件安装

1、首先说一下本次情况&#xff0c;office的版本是2019&#xff0c;后安装的Endnote 9。旧版word也可按此方法尝试。 2、先找到关键的EndNote Cwyw.dll文件。应在此目录下&#xff1a;C:\Program Files (x86)\EndNote X7\Product-Support\CWYW。 3、如没有EndNote Cwyw.dll文…

DETR论文,基于transformer的目标检测网络 DETR:End-to-End Object Detection with Transformers

transformer的基本结构: encoder-decoder的基本流程为&#xff1a; 1&#xff09;对于输入&#xff0c;首先进行embedding操作&#xff0c;即将输入映射为向量的形式&#xff0c;包含两部分操作&#xff0c;第一部分是input embedding&#xff1a;例如&#xff0c;在NLP领域&…

DevEco Studio 5.0 Beta版下载链接

最新工具 - 下载中心 - 华为开发者联盟 (huawei.com)https://developer.huawei.com/consumer/cn/download/

代码随想录算法训练营第十三天

day12周日放假 二叉树理论基础: 文章链接:代码随想录 文章摘要: 满二叉树定义&#xff1a;如果一棵二叉树只有度为0的结点和度为2的结点&#xff0c;并且度为0的结点在同一层上&#xff0c;则这棵二叉树为满二叉树。 完全二叉树定义&#xff1a;在完全二叉树中&#xff0c…