You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中如何获取TextMeshPro的每行字符数及可视区域行数?

Unity TextMeshPro 核心需求解决方案

一、获取每行的字符数量

直接借助TextMeshPro的TextInfo属性,其内置的lineInfo数组存储了每一行的索引信息,通过firstCharacterIndex与lastCharacterIndex的差值即可计算出对应行的字符数:

using TMPro;
using UnityEngine;

public class TMPLineCharCounter : MonoBehaviour
{
    public TextMeshProUGUI targetText;

    void CalculateEachLineCharCount()
    {
        if (targetText == null) return;
        
        targetText.ForceMeshUpdate(); // 强制更新文本网格,避免数据滞后
        TMP_TextInfo textInfo = targetText.textInfo;
        
        for (int i = 0; i < textInfo.lineCount; i++)
        {
            TMP_LineInfo lineInfo = textInfo.lineInfo[i];
            // 跳过空行(空行的首尾索引为-1)
            if (lineInfo.firstCharacterIndex == -1) continue;
            
            int charCount = lineInfo.lastCharacterIndex - lineInfo.firstCharacterIndex + 1;
            Debug.Log($"第{i+1}行字符数:{charCount}");
        }
    }
}

注意:文本动态修改后必须调用ForceMeshUpdate(),否则会获取到旧的行数据。

二、滚动视图中获取可视区域内的行数

结合ScrollRect的视口(Viewport)与TextMeshPro每行的位置信息,将行的世界坐标转换为视口本地坐标后,判断是否处于视口范围内即可:

using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class TMPVisibleLineDetector : MonoBehaviour
{
    public ScrollRect scrollRect;
    public TextMeshProUGUI targetText;

    int GetCurrentVisibleLineCount()
    {
        if (scrollRect == null || targetText == null) return 0;
        
        targetText.ForceMeshUpdate();
        TMP_TextInfo textInfo = targetText.textInfo;
        RectTransform viewportRect = scrollRect.viewport;
        RectTransform textRect = targetText.rectTransform;
        
        int visibleLineCount = 0;
        
        for (int i = 0; i < textInfo.lineCount; i++)
        {
            TMP_LineInfo lineInfo = textInfo.lineInfo[i];
            if (lineInfo.firstCharacterIndex == -1) continue;
            
            // 转换行的顶部、底部坐标到视口本地坐标系
            Vector3 lineTopWorld = textRect.TransformPoint(lineInfo.lineExtents.max);
            Vector3 lineTopLocal = viewportRect.InverseTransformPoint(lineTopWorld);
            
            Vector3 lineBottomWorld = textRect.TransformPoint(lineInfo.lineExtents.min);
            Vector3 lineBottomLocal = viewportRect.InverseTransformPoint(lineBottomWorld);
            
            // 判断行是否与视口重叠:行底部未超出视口顶部,且行顶部未超出视口底部
            bool isVisible = lineBottomLocal.y < viewportRect.rect.height && lineTopLocal.y > 0;
            if (isVisible) visibleLineCount++;
        }
        
        return visibleLineCount;
    }

    // 绑定到ScrollRect的OnValueChanged事件,滚动时实时计算
    void OnScrollUpdated()
    {
        int visibleLines = GetCurrentVisibleLineCount();
        Debug.Log($"当前可视行数:{visibleLines}");
    }
}

说明:

  • 若为水平滚动视图,只需将判断逻辑中的y轴替换为x轴即可。
  • 视口坐标系以左下角为原点,所以判断条件需确保行的有效区域落在视口范围内。

内容的提问来源于stack exchange,提问作者fr000g

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 16:27:26