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

如何在Godot 4中实现适配固定尺寸的Label3D文本显示?

解决Label3D文本超出固定3D表面边界的两种方案

方案1:动态缩小字体适配固定尺寸

核心思路是实时测量文本渲染后的宽度,逐步缩小字体大小,直到文本宽度不超过目标3D表面的可用宽度,同时设置最小字体下限避免文字过小无法阅读。

实现步骤

  1. 定义目标最大宽度(即3D表面允许的文本显示宽度)和最小字体大小阈值。
  2. 监听Label3D的文本变化事件,或在文本更新后主动触发尺寸检查。
  3. 使用UI Toolkit的TextMeasurementService测量当前字体下的文本宽度,若超出目标宽度则逐步减小字体,直到符合要求或达到最小字体。

代码示例

using UnityEngine;
using UnityEngine.UIElements;

[RequireComponent(typeof(Label3D))]
public class AutoResizeLabel3D : MonoBehaviour
{
    [SerializeField] private float maxAllowedWidth = 2f; // 3D空间中的目标宽度(单位:米)
    [SerializeField] private float minFontSize = 12f;
    private Label3D label3D;
    private TextMeasurementService textMeasurement;

    private void Awake()
    {
        label3D = GetComponent<Label3D>();
        textMeasurement = new TextMeasurementService();
        // 监听文本变化,自动触发调整
        label3D.RegisterCallback<ChangeEvent<string>>(OnTextChanged);
        // 初始化时调整一次
        AdjustFontSizeToFit();
    }

    private void OnTextChanged(ChangeEvent<string> evt)
    {
        AdjustFontSizeToFit();
    }

    private void AdjustFontSizeToFit()
    {
        if (string.IsNullOrEmpty(label3D.text)) return;

        float currentFontSize = label3D.style.fontSize.value.value;
        // 测量当前字体下的文本尺寸
        Vector2 textSize = textMeasurement.MeasureText(label3D.text, label3D.style);
        // 转换为3D空间中的实际宽度
        float textWorldWidth = textSize.x * label3D.transform.localScale.x;

        // 超出宽度且字体大于最小值时,逐步缩小
        while (textWorldWidth > maxAllowedWidth && currentFontSize > minFontSize)
        {
            currentFontSize -= 1f;
            label3D.style.fontSize = currentFontSize;
            textSize = textMeasurement.MeasureText(label3D.text, label3D.style);
            textWorldWidth = textSize.x * label3D.transform.localScale.x;
        }

        // 确保字体不低于最小值
        if (currentFontSize < minFontSize)
        {
            label3D.style.fontSize = minFontSize;
        }
    }
}

方案2:文本截断显示

核心思路是计算当前字体下能容纳的最大文本长度,对原文本进行截断并添加省略号,保证显示内容不超出边界。

实现步骤

  1. 定义目标最大宽度,使用TextMeasurementService测量文本片段的宽度。
  2. 从原文本开头逐步截取字符,每次测量截取后的文本宽度,直到接近目标宽度时停止,添加省略号。

代码示例

using UnityEngine;
using UnityEngine.UIElements;

[RequireComponent(typeof(Label3D))]
public class TruncateLabel3D : MonoBehaviour
{
    [SerializeField] private float maxAllowedWidth = 2f;
    private Label3D label3D;
    private TextMeasurementService textMeasurement;
    private string originalText;

    private void Awake()
    {
        label3D = GetComponent<Label3D>();
        textMeasurement = new TextMeasurementService();
        label3D.RegisterCallback<ChangeEvent<string>>(OnTextChanged);
    }

    private void OnTextChanged(ChangeEvent<string> evt)
    {
        originalText = evt.newValue;
        TruncateTextToFit();
    }

    private void TruncateTextToFit()
    {
        if (string.IsNullOrEmpty(originalText))
        {
            label3D.text = originalText;
            return;
        }

        string truncatedText = originalText;
        Vector2 textSize = textMeasurement.MeasureText(truncatedText, label3D.style);
        float textWorldWidth = textSize.x * label3D.transform.localScale.x;

        // 超出宽度时逐步截断文本
        while (textWorldWidth > maxAllowedWidth && truncatedText.Length > 1)
        {
            truncatedText = truncatedText.Substring(0, truncatedText.Length - 1);
            // 拼接省略号并测量宽度
            string displayText = truncatedText.EndsWith("...") ? truncatedText : $"{truncatedText}...";
            textSize = textMeasurement.MeasureText(displayText, label3D.style);
            textWorldWidth = textSize.x * label3D.transform.localScale.x;
        }

        // 设置最终截断后的文本
        label3D.text = truncatedText.EndsWith("...") ? truncatedText : $"{truncatedText}...";
    }
}

注意事项

  • maxAllowedWidth需根据3D表面实际尺寸调整,单位为米,与Label3D所在对象的缩放相关。
  • 若Label3D的transform.localScale有变化,需在缩放改变时重新触发调整逻辑。
  • 优先完整显示文本选方案1,优先保证文本可读性(避免字体过小)选方案2。

内容的提问来源于stack exchange,提问作者Martin Häusler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 12:46:27