Unity TextMeshPro — Count Displayed Lines and Get Last Character Position

Unity TextMeshPro — Count Displayed Lines and Get Last Character Position

Updated: October 30, 2025 — by Appalo

This Unity tutorial teaches you how to count displayed lines and find the position of the last visible character in a TextMeshProUGUI text — without using Update(). The method uses onTextChanged for optimized performance and instant layout updates.

🔹 The Problem with Update()

Many Unity developers call Update() every frame to detect text changes in TextMeshPro. This consumes unnecessary CPU resources when the text doesn’t change.

🔹 The Optimized Solution

Using TextMeshPro’s onTextChanged event allows your script to update only when text content changes. Below is the full optimized script:

// TMPTextAnalyzer.cs
using UnityEngine;
using TMPro;

public class TMPTextAnalyzer : MonoBehaviour
{
    [Header("References")]
    public TextMeshProUGUI text;      // The TMP component to analyze
    public RectTransform target;      // Object to position at the end of text
    public float offsetX = 0f;
    public float offsetY = 0f;

    void OnEnable()
    {
        if (text == null) text = GetComponent();
        AnalyzeText();
        text.onTextChanged.AddListener(OnTextChanged);
    }

    void OnDisable()
    {
        text.onTextChanged.RemoveListener(OnTextChanged);
    }

    private void OnTextChanged(Object obj)
    {
        AnalyzeText();
    }

    private void AnalyzeText()
    {
        if (text.textInfo == null || text.text.Length == 0)
            return;

        text.ForceMeshUpdate();

        // ---- Count and Log Each Line ----
        for (int i = 0; i < text.textInfo.lineCount; i++)
        {
            int startIndex = text.textInfo.lineInfo[i].firstCharacterIndex;
            int endIndex = (i == text.textInfo.lineCount - 1)
                ? text.text.Length
                : text.textInfo.lineInfo[i + 1].firstCharacterIndex;
            int length = endIndex - startIndex;

            Debug.Log($"Line {i + 1}: " + text.text.Substring(startIndex, length));
        }

        // ---- Get Last Character Position ----
        if (text.textInfo.characterCount > 0 && target != null)
        {
            var lastChar = text.textInfo.characterInfo[text.textInfo.characterCount - 1];
            Vector3 bottomLeft = lastChar.bottomLeft;
            Vector3 worldBottomLeft = text.transform.TransformPoint(bottomLeft);
            Vector3 local = target.parent.InverseTransformPoint(worldBottomLeft);

            target.localPosition = new Vector3(local.x - offsetX, local.y - offsetY, 0);
        }
    }
}

💡 How It Works

  • onTextChanged — fires automatically when TextMeshPro content changes.
  • ForceMeshUpdate() — instantly refreshes text layout data.
  • lineInfo — provides start and end indices for each line.
  • characterInfo — gives position data for each visible character.

⚙️ Setup Guide: Attach Text & Target in Canvas

  1. In your Unity Canvas, create a new TextMeshPro - Text (UI) element.
  2. Type some sample text (e.g., “This is a test for line detection”).
  3. Create an empty GameObject and name it TMPTextAnalyzer.
  4. Add the above script to it (drag & drop into Inspector).
  5. Drag your TextMeshProUGUI object into the script’s Text field.
  6. Create an Image or UI Icon inside the same Canvas (for example, a cursor).
  7. Assign that image’s RectTransform into the Target field — this will move to the end of text.
  8. Press Play — the console will display all text lines and the target will position at the end automatically.

🚀 Benefits of This Approach

  • ✅ No Update() loop — better performance.
  • ✅ Automatically updates only when text changes.
  • ✅ Perfect for subtitles, chat systems, typing effects, or reading apps.

🧩 SEO Keywords

Unity TextMeshPro line count, TextMeshPro last character, Unity UI text tutorial, Appalo Unity tools, TMP text analyzer, Unity text position, TextMeshProUGUI event

📘 Conclusion

By using onTextChanged instead of Update(), you can significantly optimize your Unity UI logic. This method delivers precise line and character position data while saving CPU resources — ideal for performance-critical games and reading apps.

Appalo Learn more at Appalo.net.