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

Unity中TextMeshPro渲染过慢致BoxCollider2D无法快速适配问题求助

问题:Unity中快速为TextMeshPro生成匹配包围盒的BoxCollider2D

我在Unity用C#开发,需要给TextMeshPro文本添加和文本尺寸匹配的BoxCollider2D(只要包围盒,不需要精确文本形状)。现在遇到两个问题:

  • 调用GetRenderedValues获取渲染尺寸时,生成实际值耗时极长
  • 如果不延迟更新BoxCollider2D尺寸,返回值只有0.00001,已经用了ForceMeshUpdate但没解决

现有创建TMP的代码

foreach (var programs in uniquePrograms)
{
    //Create each Programs from Initial Full data List
    GameObject createProgram = (GameObject) Instantiate(ProgramPreFab);
    createProgram.name = programs;

    //Creates TextMeshPro Object (Should be used for Data Points) as child of First Child Component (should be Vertical layout - will likely need to be more specific in future)
    List<DataClass.DataStructure> dataSplit = FullData.Where(x => x.program == programs).ToList();

    foreach (var data in dataSplit)
    {
        //Create TextMeshPro and associated Box Collider Variable & ensure it's sorting order is always in front of it's parent
        TextMeshPro dataPoint = (TextMeshPro)Instantiate(DataPointTMP, createProgram.transform.GetChild(0));
        dataPoint.sortingOrder = createProgram.GetComponent<Renderer>().sortingOrder + 1;
        
        //Update TMP with Data Point Name (ForceMeshUpdate may be need to ensure the text is there so the BoxCollider will have the correct values)
        dataPoint.text = data.dataName;
        dataPoint.ForceMeshUpdate();
        dataPoint.name = data.dataName;

        //Add TMP to createdDataPoint to add Box Collider in StartUpGenerateBoxColliders function (next)
        createdDataPoints.Add(dataPoint);
        
    }
}

尝试过的延迟更新代码(耗时过长)

IEnumerator WaitToCreateCollider()
{
    yield return new WaitForEndOfFrame();
    StartUpGenerateBoxColliders();
}  

void StartUpGenerateBoxColliders()
{
    foreach (var dataPoint in createdDataPoints)
    {
        BoxCollider2D boxCollider2D = dataPoint.GetComponent<BoxCollider2D>();
        Vector2 textSize =  dataPoint.GetRenderedValues(false);
        boxCollider2D.size = textSize;
        Debug.Log(dataPoint.name + "Box Colider Updated");
    }
}

上述代码均在Start方法中调用,目前虽能实现功能,但等待耗时过久,求加速文本渲染/碰撞体更新的方法。


优化方案

1. 改用异步渲染+分帧处理碰撞体

ForceMeshUpdate()默认同步执行,批量调用会阻塞主线程。改用异步更新,再分帧处理已完成渲染的文本:

// 创建TMP时替换同步ForceMeshUpdate为异步
dataPoint.text = data.dataName;
dataPoint.ForceMeshUpdate(TMP_FontAsset.UpdateType.Asynchronous); // 异步更新网格
dataPoint.name = data.dataName;
createdDataPoints.Add(dataPoint);

然后用分帧协程更新碰撞体,避免单帧负载过高:

IEnumerator UpdateCollidersOverFrames()
{
    int processedCount = 0;
    while (processedCount < createdDataPoints.Count)
    {
        var dataPoint = createdDataPoints[processedCount];
        if (dataPoint.IsGeometryReady) // 检查文本网格是否生成完成
        {
            BoxCollider2D boxCollider2D = dataPoint.GetComponent<BoxCollider2D>();
            Vector2 textSize = dataPoint.GetRenderedValues(false);
            boxCollider2D.size = textSize;
            Debug.Log($"{dataPoint.name} Box Collider Updated");
            processedCount++;
        }
        yield return null; // 每帧处理一个,避免卡顿
    }
}

调用时直接启动这个协程即可,无需等待整帧结束。

2. 预计算文本尺寸(无需等待渲染)

如果文本内容已知,直接用TMP_TextUtilities.GetTextBounds预计算尺寸,跳过实际渲染步骤,速度最快:

foreach (var data in dataSplit)
{
    TextMeshPro dataPoint = (TextMeshPro)Instantiate(DataPointTMP, createProgram.transform.GetChild(0));
    dataPoint.sortingOrder = createProgram.GetComponent<Renderer>().sortingOrder + 1;
    
    dataPoint.text = data.dataName;
    dataPoint.name = data.dataName;

    // 预计算文本包围盒,无需等待渲染
    Bounds textBounds = TMP_TextUtilities.GetTextBounds(
        dataPoint.text,
        dataPoint.font,
        dataPoint.fontSize,
        dataPoint.characterSpacing
    );

    // 直接设置碰撞体尺寸
    BoxCollider2D boxCollider2D = dataPoint.GetComponent<BoxCollider2D>();
    boxCollider2D.size = new Vector2(textBounds.size.x, textBounds.size.y);
    
    createdDataPoints.Add(dataPoint);
}

这个方法完全绕开了运行时渲染等待,适合批量生成文本的场景。

3. 优化TextMeshPro设置减少渲染开销

  • 关闭Word Wrapping、Extra Padding等不需要的特性,减少网格计算量
  • 确保使用的字体已预生成Atlas(在TextMeshPro Font Asset中勾选Include Font Atlas),避免运行时动态生成图集
  • 降低字体的Rendering Mode(比如从SDF改为Bitmap,如果视觉要求允许)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 22:57:10