为什么 TextMeshPro 在设置文本后不更新 textBounds?

Rom*_*man 5 c# unity-game-engine

我在悬停时实现了一个工具提示系统。为此,我使用 textmeshpro 文本和图像。该图像应该是一个简单的背景,具体取决于文本的长度,而文本的长度总是不同的。

如果我将鼠标悬停在某个元素上,textmeshpro 文本将被替换。背景图像被移动到元素上,并且大小将根据文本的长度而变化:

// Hover over slot in
public void OnPointerEnter(PointerEventData eventData) {
    if (currentItem != null) {
        Debug.Log("hover over slot item in");
        GamePlay.EnableCanvas(GamePlay.GetHoverCanvas());

        TextMeshProUGUI txtMeshPro = GamePlay.GetHoverCanvas().GetComponentInChildren<TextMeshProUGUI>();

        Debug.Log(currentItem.GetItemDescription(currentItem));
        txtMeshPro.text = currentItem.GetItemDescription(currentItem);

        var hoverCanvasText = txtMeshPro.GetComponent<RectTransform>();
        var hoverCanvasTextBG = GamePlay.GetHoverCanvas().GetComponentInChildren<Image>().GetComponent<RectTransform>();

        hoverCanvasText.position = new Vector3(this.GetComponent<RectTransform>().position.x, this.GetComponent<RectTransform>().position.y + 50, 0);

        hoverCanvasTextBG.position = new Vector3(this.GetComponent<RectTransform>().position.x, this.GetComponent<RectTransform>().position.y + 50, 0);
        hoverCanvasTextBG.sizeDelta = new Vector2(txtMeshPro.textBounds.size.x + 15, txtMeshPro.textBounds.size.y + 15);
        // No clue why image is not resized properly on first hover
    }     
}
Run Code Online (Sandbox Code Playgroud)

我遇到的奇怪问题是,第一次将鼠标悬停在元素上时,图像大小不会改变。

替换文本和更改位置总是没有问题的。

问题描述:

首先将鼠标悬停在元素 A 上:图像背景大小根本不会改变。

第二次将鼠标悬停在元素 B 上:图像背景大小发生变化,但具有元素 A 的正确大小

第三次将鼠标悬停在元素 A 上:图像背景大小发生变化,但具有元素 B 的正确大小

这怎么可能?我不明白这里发生了什么。该代码对于位置没有任何问题,为什么相同的逻辑对于尺寸不起作用。

注意:我对 Unity 很陌生,已经修补了几天了,所以我可能是一个非常简单的问题,但经过几个小时的研究后,我还没有发现任何有用的东西。

Fog*_*zie 3

设置 a 的文本后TextMeshProUGUItextBounds及其size直到下一帧才会更新。这是由 Unity 的延迟布局重建造成的。在他们的UI 布局文档中,它写道:

重建不会立即发生,而是在当前帧结束时、渲染发生之前发生。它不是立即发生的原因是,这可能会导致布局在同一帧期间可能被重建多次,这对性能不利。

我要继续猜测GamePlay.GetHoverCanvas()是维护一个从未被破坏的对象,因此,您的代码在除了第一次运行之外的所有情况下都可以工作。

可能有几种方法可以解决这个问题,但最简单的方法是Canvas.ForceUpdateCanvases()在设置text和读取 的大小之间调用textbounds。它不是最快的函数,但应该可以解决问题。

另一种选择是启动一个协程,该协程设置一个text帧,产生下一帧,然后textbounds在执行的第二帧上读取 ,而不是同步函数。(这可能会导致尺寸突然出现并且看起来不合需要)。

  • 非常感谢您的详细解释。这对我很有帮助。 (2认同)