using UnityEngine; using System.Collections; using TMPro; using Pixelplacement; namespace TMPro.Examples { [RequireComponent(typeof(TMP_Text))] public class WarpTextExample : MonoBehaviour { private TMP_Text m_TextComponent; [Header("Spline Reference")] public Spline spline; // Assign this in the inspector [Header("Warp Settings")] public float AngleMultiplier = 1.0f; public float NormalOffset = 20.0f; // Distance above the spline void Awake() { m_TextComponent = GetComponent(); } void Start() { if (spline == null) { Debug.LogError("Spline reference not set on WarpTextExample!"); enabled = false; return; } StartCoroutine(WarpText()); } IEnumerator WarpText() { Vector3[] vertices; Matrix4x4 matrix; m_TextComponent.havePropertiesChanged = true; // Force update while (true) { m_TextComponent.ForceMeshUpdate(); TMP_TextInfo textInfo = m_TextComponent.textInfo; int characterCount = textInfo.characterCount; if (characterCount == 0) { yield return null; continue; } float boundsMinX = m_TextComponent.bounds.min.x; float boundsMaxX = m_TextComponent.bounds.max.x; for (int i = 0; i < characterCount; i++) { if (!textInfo.characterInfo[i].isVisible) continue; int vertexIndex = textInfo.characterInfo[i].vertexIndex; int materialIndex = textInfo.characterInfo[i].materialReferenceIndex; vertices = textInfo.meshInfo[materialIndex].vertices; // Compute the baseline mid point for each character Vector3 offsetToMidBaseline = new Vector2( (vertices[vertexIndex + 0].x + vertices[vertexIndex + 2].x) / 2, textInfo.characterInfo[i].baseLine); // Remove the offset so we can warp around the origin vertices[vertexIndex + 0] += -offsetToMidBaseline; vertices[vertexIndex + 1] += -offsetToMidBaseline; vertices[vertexIndex + 2] += -offsetToMidBaseline; vertices[vertexIndex + 3] += -offsetToMidBaseline; // Normalized position along the text bounds float t = (offsetToMidBaseline.x - boundsMinX) / (boundsMaxX - boundsMinX); t = Mathf.Clamp01(t); Vector3 localSplinePos = spline.GetPosition(t); Vector3 localSplineTangent = spline.GetDirection(t, true).normalized; // Calculate 2D normal (perpendicular to tangent) Vector3 normal2D = new Vector3(-localSplineTangent.y, localSplineTangent.x, 0).normalized; Vector3 offsetPos = localSplinePos + normal2D * NormalOffset; float angle = Mathf.Atan2(localSplineTangent.y, localSplineTangent.x) * Mathf.Rad2Deg * AngleMultiplier; matrix = Matrix4x4.TRS(offsetPos, Quaternion.Euler(0, 0, angle), Vector3.one); vertices[vertexIndex + 0] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 0]); vertices[vertexIndex + 1] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 1]); vertices[vertexIndex + 2] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 2]); vertices[vertexIndex + 3] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 3]); vertices[vertexIndex + 0] += offsetToMidBaseline; vertices[vertexIndex + 1] += offsetToMidBaseline; vertices[vertexIndex + 2] += offsetToMidBaseline; vertices[vertexIndex + 3] += offsetToMidBaseline; } m_TextComponent.UpdateVertexData(); yield return new WaitForSeconds(0.025f); } } } }