Unity TMP文字移动效果

前言

看见很多游戏有很特殊的波浪形文字效果,于是来尝试一下控制TMP文字顶点的方式达到类似效果。

原理

挂载tmp text,在里面随便放入非空格字符。

tmp text组件开放了textInfo接口,也就是GetComponent<TextMeshProUGUI>().textInfo可以获取text字符串信息:

 characterInfo[i].vertexIndex用于找到这个字符起始index;meshInfo[TMP_CharacterInfo.materialReferenceIndex]用于获取mesh信息,再进一层meshInfo.vertices即可拿到顶点信息。

我们就是强行修改vertices信息,然后调用TextMeshProUGUI.UpdateVertexData()即可完成text不同字符间的修改。

保存原始字符顶点vertices信息

//tmp组件
TextMeshProUGUI m_txtSelf = null;
//移动周期
float m_moveTotalTime = 1f;
//上下浮动幅度
float m_amplitude = 100;
Vector3[] m_rawVertex;

public void Awake()
{
    m_txtSelf = transform.GetComponent<TextMeshProUGUI>();
}

private void GetRawVertex()
{
    m_txtSelf.ForceMeshUpdate();
    if (m_txtSelf.textInfo.characterCount > 0)
    {
        TMP_CharacterInfo charInfo = m_txtSelf.textInfo.characterInfo[0];
        TMP_MeshInfo meshInfo = m_txtSelf.textInfo.meshInfo[charInfo.materialReferenceIndex];
        //创建对象来保存初始值
        m_rawVertex = new Vector3[meshInfo.vertices.Length];
        for (int i = 0; i < meshInfo.vertices.Length; i++)
        {
            m_rawVertex[i] = new Vector3(meshInfo.vertices[i].x, meshInfo.vertices[i].y, meshInfo.vertices[i].z);
        }
    }
}

public void Start()
{
    GetRawVertex();
}

所有字符一起移动

用协程每隔一段时间做一次循环运动,用dotween.to附加lamda表达式来完成字符串移动:

public void Start()
{
    GetRawVertex();
    StartCoroutine(Shake());
}
public IEnumerator Shake()
{
    while(true)
    {
        Tweener tweener = DOTween.To(() => 0f, y =>
        {
            for (int i = 0; i < m_txtSelf.textInfo.characterCount; i++)
            {
                // 获取字符信息和MeshInfo
                TMP_CharacterInfo currentCharInfo = m_txtSelf.textInfo.characterInfo[i];
                TMP_MeshInfo meshInfo = m_txtSelf.textInfo.meshInfo[currentCharInfo.materialReferenceIndex];

                int nextVertexIndex = meshInfo.vertices.Length;
                if (i < m_txtSelf.textInfo.characterCount - 1)
                {
                    TMP_CharacterInfo nextCharInfo = m_txtSelf.textInfo.characterInfo[i + 1];
                    nextVertexIndex = nextCharInfo.vertexIndex;
                }

                // 获取起始顶点索引
                int vertexIndex = currentCharInfo.vertexIndex;

                // 顶点偏移
                for (int j = vertexIndex; j < nextVertexIndex; j++)
                {
                    float yOffset = y;
                    if (yOffset >= 0 && yOffset <= 1)
                    {
                        meshInfo.vertices[j] = m_rawVertex[j] + Mathf.Sin(yOffset * Mathf.PI) * Vector3.up * m_amplitude;
                    }
                }
            }
            m_txtSelf.UpdateVertexData();
        }, 2, m_moveTotalTime);

        yield return new WaitForSeconds(m_moveTotalTime);
    }
}

 效果如下显示:

 每个字符规律跳动

就需要在y->yOffset中加入位置参数变量,用以形成类波浪效果:

float yOffset = y - (float)i / m_txtSelf.textInfo.characterCount;

 至此即可完成。

全部代码

using System.Collections;
using UnityEngine;
using TMPro;
using DG.Tweening;

public class test : MonoBehaviour
{
    //tmp组件
    TextMeshProUGUI m_txtSelf = null;
    //移动周期
    float m_moveTotalTime = 1f;
    //上下浮动幅度
    float m_amplitude = 100;
    Vector3[] m_rawVertex;

    public void Awake()
    {
        m_txtSelf = transform.GetComponent<TextMeshProUGUI>();
    }

    private void GetRawVertex()
    {
        m_txtSelf.ForceMeshUpdate();
        if (m_txtSelf.textInfo.characterCount > 0)
        {
            TMP_CharacterInfo charInfo = m_txtSelf.textInfo.characterInfo[0];
            TMP_MeshInfo meshInfo = m_txtSelf.textInfo.meshInfo[charInfo.materialReferenceIndex];
            //创建对象来保存初始值
            m_rawVertex = new Vector3[meshInfo.vertices.Length];
            for (int i = 0; i < meshInfo.vertices.Length; i++)
            {
                m_rawVertex[i] = new Vector3(meshInfo.vertices[i].x, meshInfo.vertices[i].y, meshInfo.vertices[i].z);
            }
        }
    }

    public void Start()
    {
        GetRawVertex();
        StartCoroutine(Shake());
    }
    public IEnumerator Shake()
    {
        yield return new WaitForSeconds(1);
        while (true)
        {
            Tweener tweener = DOTween.To(() => 0f, y =>
            {
                for (int i = 0; i < m_txtSelf.textInfo.characterCount; i++)
                {
                    // 获取字符信息和MeshInfo
                    TMP_CharacterInfo currentCharInfo = m_txtSelf.textInfo.characterInfo[i];
                    TMP_MeshInfo meshInfo = m_txtSelf.textInfo.meshInfo[currentCharInfo.materialReferenceIndex];

                    int nextVertexIndex = meshInfo.vertices.Length;
                    if (i < m_txtSelf.textInfo.characterCount - 1)
                    {
                        TMP_CharacterInfo nextCharInfo = m_txtSelf.textInfo.characterInfo[i + 1];
                        nextVertexIndex = nextCharInfo.vertexIndex;
                    }

                    // 获取起始顶点索引
                    int vertexIndex = currentCharInfo.vertexIndex;

                    // 顶点偏移
                    for (int j = vertexIndex; j < nextVertexIndex; j++)
                    {
                        float yOffset = y - (float)i / m_txtSelf.textInfo.characterCount;
                        if (yOffset >= 0 && yOffset <= 1)
                        {
                            meshInfo.vertices[j] = m_rawVertex[j] + Mathf.Sin(yOffset * Mathf.PI) * Vector3.up * m_amplitude;
                        }
                    }
                }
                m_txtSelf.UpdateVertexData();
            }, 2, m_moveTotalTime);

            yield return new WaitForSeconds(m_moveTotalTime);
        }
    }
}

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

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

相关文章

Linux:线程控制和原生线程库

文章目录 线程的id和LWP线程的终止线程的返回值问题关于原生线程库问题 本篇总结的内容主要是关于线程的控制专题 线程的id和LWP 对于获取线程的id来说&#xff0c;在Linux系统中存在这样的调用 这个调用就可以获取返回当前线程的id 先写出下面的实例代码 #include <ios…

设计模式学习笔记 - 设计原则 - 8.迪米特法则(LOD)

前言 迪米特法则&#xff0c;是一个非常实用的原则。利用这个原则&#xff0c;可以帮我们实现代码的 “高内聚、松耦合”。 围绕下面几个问题&#xff0c;来学习迪米特原则。 什么是 “高内聚、松耦合”&#xff1f;如何利用迪米特法则来实现 高内聚、松耦合&#xff1f;哪些…

【Python】FastAPI 项目创建 与 Docker 部署

文章目录 前言&需求描述1. 本地FastAPI1.1 Python 环境准备1.2 本地 Pycharm 创建FastAPI项目 2. Python FastAPI 部署2.1 服务器配置Python环境2.2.1 下载与配置Git、Pyenv等工具2.2.2 下载与配置Python 2.2 FastAPI 打包成镜像2.2.1 项目准备所需环境文件2.2.2 编写Docke…

Java基于SpringBoot的在线文档管理系统的设计与实现论文

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;在线文档管理当然也不能排除在外。在线文档管理系统是以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&am…

合并两个有序链表

题目 题目链接 合并两个排序的链表_牛客题霸_牛客网 题目描述 代码实现 class Solution { public:/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可** * param pHead1 ListNode类 * param pHead2 ListNode类 * return …

1分钟学会Python字符串前后缀与编解码

1.前缀和后缀 前缀和后缀指的是&#xff1a;字符串是否以指定字符开头和结尾 2.startswith() 判断字符串是否以指定字符开头&#xff0c;若是返回True&#xff0c;若不是返回False str1 "HelloPython"print(str1.startswith("Hello")) # Trueprint…

Python 微信自动化工具wxauto开发系列01(2024年3月可用 支持3.9最新微信)

下载链接&#xff1a;GitHub - cluic/wxauto: Windows版本微信客户端&#xff08;非网页版&#xff09;自动化&#xff0c;可实现简单的发送、接收微信消息&#xff0c;简单微信机器人d 推荐大家在github下载&#xff1a; git clone https://github.com/cluic/wxauto.git cd w…

数据结构——基本术语和概念

目录 1.数据 2.数据元素 3.数据项 4.数据对象 数据元素与数据对象 5.数据结构 1.逻辑结构 逻辑结构的种类 划分方式1 1.线性结构 2.非线性结构 ​ 划分方式2——四类基本逻辑结构 2.物理结构&#xff08;存储结构&#xff09; 1.顺序存储结构 2.链接存储结构 3…

【贪心算法】Leetcode 455.分发饼干 376. 摆动序列 53. 最大子数组和

【贪心算法】Leetcode 455 分发饼干 376. 摆动序列【规律很多】53. 最大子数组和 455 分发饼干局部最优推全局最优&#xff1a;尽量用大饼干去满足大胃口的小朋友 376. 摆动序列【规律很多】思想&#xff1a;注意考虑一个坡度留首尾两个点、平坡、首尾 53. 最大子数组和【好思想…

SD-WAN助力企业数据传输安全

随着企业网络需求的不断增长&#xff0c;SD-WAN成为企业网络组网的首选方案&#xff0c;能够实现多种网络拓扑结构的无缝连接&#xff0c;其中包括总部-分支、总部-分支-数据中心、总部-数据中心、总部-分支-云服务等。如何确保企业数据在传输过程中的安全性成为企业关注的重要…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的植物病害检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;开发高效的植物病害检测系统对于提升农业生产效率和作物健康管理意义重大。本篇博客详细阐述了如何运用深度学习技术构建一个植物病害检测系统&#xff0c;并提供了完整的实现代码。该系统基于先进的YOLOv8算法&#xff0c;对YOLOv7、YOLOv6、YOLOv5进行了性能…

用指针数组完成单词倒排

描述 对字符串中的所有单词进行倒排。 说明&#xff1a; 1、构成单词的字符只有26个大写或小写英文字母&#xff1b; 2、非构成单词的字符均视为单词间隔符&#xff1b; 3、要求倒排后的单词间隔符以一个空格表示&#xff1b;如果原字符串中相邻单词间有多个间隔符时&…

更换个人开发环境后,pycharm连接服务器报错Authentication failed

原因&#xff1a;服务器中更换个人开发环境后&#xff0c;密码变了。 解决&#xff1a;在pycharm中修改服务器开发环境密码即可。 1 找到Tools-Depolyment-Configuration 2 点击SSH Configuration后的省略号 3 修改这里面的Password即可

SVN教程-SVN的基本使用

SVN&#xff08;Apache Subversion&#xff09;是一款强大的集中式版本控制系统&#xff0c;它在软件开发项目中扮演着至关重要的角色&#xff0c;用于有效地跟踪、记录和管理代码的演变过程。与分布式系统相比&#xff0c;SVN 的集中式架构使得团队能够更加协同地进行开发&…

Docker将本地的镜像上传到私有仓库

使用register镜像创建私有仓库 [rootopenEuler-node1 ~]# docker run --restartalways -d -p 5000:5000 -v /opt/data/regostry:/var/lib/registry registry:2[rootopenEuler-node1 ~]# docker images REPOSITORY TAG IMAGE…

DataIntegrityViolationException异常产生原因及解决方案

DataIntegrityViolationException异常产生原因及解决方案 01 异常的发生场景 在我新写了一个接口之后出现的 //org.springframework.dao.DataIntegrityViolationException日志报错的意思是参数设置了一个错误的值 02 异常的产生及其原因 我最开始认为是MySQL数据库表设计…

【学习总结】什么是DoS和DDoS

[Q&A] 什么是DoS DoS 是 “Denial of Service”&#xff08;拒绝服务&#xff09;的缩写&#xff0c;它是一种网络攻击方式&#xff0c;其目的是使目标计算机或网络资源无法为合法用户提供正常的服务。通过向目标系统发送大量请求、消耗其带宽、处理器或内存等资源&#…

网络安全: Kali Linux 使用 nmap 扫描目标主机

目录 一、实验 1.环境 2. Kali Linux (2024.1) 使用 namp 扫描目标主机 3.Kali Linux (2024.1)远程登录 Windows Server 4.Kali Linux (2024.1) 使用crunch字典工具 5.Kali Linux (2024.1)使用hydra密码工具 6.Kali Linux (2022.3) 通过SSH端口获取 Ubuntu 密码 二、问题…

备考2024年北京高考数学:20114~2023十年选择题练习和解析

距离2024年高考还有三个月的时间&#xff0c;如何用三个月的时间再提高北京数学高考的成绩&#xff1f;吃透历年真题以及背后的知识点是行之有效的方法 之一。 今天我们来看一下2014-2023年的北京市高考数学的选择题&#xff0c;从过去十年&#xff08;2014-2023&#xff09;的…

SandBox中的JavaAgent技术

8.1 JavaAgent Java Agent 是一种强大的技术&#xff0c;在运行时动态修改已加载类的字节码&#xff0c;为应用程序注入额外的功能和行为。 JDK 1.5 支持静态 Instrumentation&#xff0c;基本的思路是在 JVM 启动的时候添加一个代理&#xff08;javaagent&#xff09;&#…