效果:
using TMPro;
using UnityEngine;
using NaughtyAttributes;
[ExecuteInEditMode]
public class TMTextPerpective : MonoBehaviour
{
[OnValueChanged("DoPerspective")]
[Range(-1f, 1f)]
public float CenterBias = 0f;
[OnValueChanged("DoPerspective")]
[Range(0f, 100f)]
public float PValue = 0f;
TMP_Text m_Text;
void Awake()
{
m_Text = GetComponent<TMP_Text>();
TMPro_EventManager.TEXT_CHANGED_EVENT.Add(OnTextMeshChanged);
}
void Start()
{
DoPerspective();
}
// Update is called once per frame
void Update()
{
}
void OnTextMeshChanged(Object o)
{
if (!Application.isPlaying)
return;
if (o == m_Text)
{
ChangeText2Perspective();
}
}
void ChangeText2Perspective()
{
//Debug.Log("-----------------ChangeText2Perspective--------------");
TMP_TextInfo textInfo = m_Text.textInfo;
int characterCount = textInfo.characterCount;
if (characterCount == 0) return;
float x_min = m_Text.bounds.min.x;
float x_max = m_Text.bounds.max.x;
float y_min = m_Text.bounds.min.y;
float y_max = m_Text.bounds.max.y;
float center_x = x_min + (x_max - x_min) * ((CenterBias + 1f) / 2f);
//Debug.Log($"x center {center_x}");
Vector3[] vertices;
float aff_ratio = PValue / 100f;
for (int i = 0; i < characterCount; i++)
{
if (!textInfo.characterInfo[i].isVisible)
continue;
int vertexIndex = textInfo.characterInfo[i].vertexIndex;
// Get the index of the mesh used by this character.
int materialIndex = textInfo.characterInfo[i].materialReferenceIndex;
vertices = textInfo.meshInfo[materialIndex].vertices;
for (int j = 0; j < 4; j++)
{
Vector3 p = vertices[vertexIndex + j];
float iratio = (p.y - y_min) / (y_max - y_min);
//Debug.Log($"{textInfo.characterInfo[i].character} v {j} move percent {iratio} aff {aff_ratio}");
p.x = p.x + (center_x - p.x) * aff_ratio * iratio;
vertices[vertexIndex + j] = p;
}
}
m_Text.UpdateVertexData();
}
[Button("执行")]
void DoPerspective()
{
m_Text.ForceMeshUpdate();
if (!Application.isPlaying)
ChangeText2Perspective();
}
}