前言
看見很多游戲有很特殊的波浪形文字效果,于是來嘗試一下控制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);}}
}