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

Unity2D中容器宽度不足时如何水平压缩文本而非修改字号?

解决Unity2D中卡牌文本水平适配容器的高效方案

嘿,这个需求我之前做TCG卡牌描述文本时也踩过坑!Unity自带的Best Fit只会傻乎乎调字号,完全不是咱们要的水平压缩效果,给你分享几个实测好用的高效方案:

方案1:UGUI Text直接通过RectTransform缩放(快速实现)

这个是最直接的思路——先算出文本的自然宽度,再用容器宽度除以这个值得到水平缩放比例,保持垂直缩放为1,避免文字被压扁。

给你一段可以直接用的代码:

using UnityEngine;
using UnityEngine.UI;

public class CardTextScaler : MonoBehaviour
{
    [SerializeField] private Text cardText;
    [SerializeField] private RectTransform textContainer;

    void Start()
    {
        FitTextToContainer();
    }

    // 核心适配方法
    public void FitTextToContainer()
    {
        // 强制刷新布局,确保获取到准确的文本自然宽度
        LayoutRebuilder.ForceRebuildLayoutImmediate(cardText.rectTransform);
        float naturalTextWidth = cardText.preferredWidth;
        float containerWidth = textContainer.rect.width;

        if (naturalTextWidth > containerWidth)
        {
            // 计算水平缩放比例,垂直保持原比例
            float scaleRatio = containerWidth / naturalTextWidth;
            cardText.rectTransform.localScale = new Vector3(scaleRatio, 1f, 1f);
        }
        else
        {
            // 文本宽度小于容器,恢复默认缩放
            cardText.rectTransform.localScale = Vector3.one;
        }
    }

    // 动态修改文本内容时调用这个方法重新适配
    public void UpdateCardText(string newText)
    {
        cardText.text = newText;
        FitTextToContainer();
    }
}

优点:零额外依赖,代码简单高效,适配速度快;
注意点:如果文本和容器宽度差太多,缩放后文字会有点扁,不过卡牌游戏里一般文本长度不会极端超标,这个问题基本可以忽略。

方案2:使用TextMeshPro(推荐,效果更好)

如果你的项目用了TextMeshPro(强烈建议卡牌游戏用它,文字渲染清晰度甩UGUI Text几条街),思路和上面一致,但TMP的文本宽度计算更准确,缩放后的显示效果也更好。

代码示例:

using UnityEngine;
using TMPro;

public class TMPCardTextScaler : MonoBehaviour
{
    [SerializeField] private TextMeshProUGUI cardTMPText;
    [SerializeField] private RectTransform textContainer;

    void Start()
    {
        FitTMPToContainer();
    }

    public void FitTMPToContainer()
    {
        // 强制刷新TMP的网格数据,获取准确的首选宽度
        cardTMPText.ForceMeshUpdate();
        float naturalTextWidth = cardTMPText.preferredWidth;
        float containerWidth = textContainer.rect.width;

        if (naturalTextWidth > containerWidth)
        {
            float scaleRatio = containerWidth / naturalTextWidth;
            cardTMPText.rectTransform.localScale = new Vector3(scaleRatio, 1f, 1f);
        }
        else
        {
            cardTMPText.rectTransform.localScale = Vector3.one;
        }
    }

    public void UpdateCardText(string newText)
    {
        cardTMPText.text = newText;
        FitTMPToContainer();
    }
}

额外优化:你还可以给TMP设置Horizontal Overflow为Overflow,确保文本不会自动换行,这样缩放的就是完整的一行文本,完全符合卡牌文本的需求。

方案3:进阶自定义适配(平衡缩放与字号)

如果担心极端情况下缩放导致文字太扁,可以加个阈值:当缩放比例低于某个值(比如0.8)时,先稍微调小字号,再进行缩放,平衡显示效果。比如在方案2的基础上修改:

public void FitTMPToContainer()
{
    cardTMPText.ForceMeshUpdate();
    float naturalTextWidth = cardTMPText.preferredWidth;
    float containerWidth = textContainer.rect.width;
    float minScaleRatio = 0.8f; // 最小缩放比例阈值

    if (naturalTextWidth > containerWidth)
    {
        float scaleRatio = containerWidth / naturalTextWidth;
        if (scaleRatio < minScaleRatio)
        {
            // 先按比例缩小字号
            cardTMPText.fontSize *= scaleRatio / minScaleRatio;
            // 再用最小比例缩放
            cardTMPText.rectTransform.localScale = new Vector3(minScaleRatio, 1f, 1f);
        }
        else
        {
            cardTMPText.rectTransform.localScale = new Vector3(scaleRatio, 1f, 1f);
        }
    }
    else
    {
        cardTMPText.rectTransform.localScale = Vector3.one;
        // 恢复默认字号(如果之前修改过的话)
        cardTMPText.fontSize = cardTMPText.fontSizeBase;
    }
}

这个方案适合对文本显示效果要求极高的场景,不过卡牌游戏里前两个方案基本足够了。

我自己做的TCG项目就是用的方案2,动态修改卡牌描述后调用适配方法,完全满足需求,你可以试试!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:26:28