前言
看见很多游戏有很特殊的波浪形文字效果,于是来尝试一下控制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++){// 获取字符信息和MeshInfoTMP_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++){// 获取字符信息和MeshInfoTMP_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);}}
}