我已经在悬停上实现了工具提示系统。为此,我使用了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
}
}
我有一个奇怪的问题,就是我第一次将鼠标悬停在元素上时,图像大小不会改变。
替换文本和更改位置始终可以正常工作。
问题说明:
首先将鼠标悬停在元素A上:图像背景大小完全不会改变。
第二个鼠标悬停在元素B上:图像背景大小发生变化,但元素A的大小正确
将鼠标悬停在元素A上的第三次:图像背景大小发生变化,但元素B的大小正确
这怎么可能?我不明白这里发生了什么。该代码对位置没有任何影响,为什么相同的逻辑对大小不起作用。
注意:我刚接触团结,现在已经几天了,所以我可能是一个非常简单的问题,但是经过几个小时的研究,我没有发现任何有用的东西。
答案 0 :(得分:2)
您可以在分配字符串后立即使用 TMP_Text.ForceMeshUpdate();
,而不是刷新所有画布。这可确保您的文本信息在同一框架内正确无误。
如果您的文本的父级使用布局组,则您很有可能也需要更新它们。你用 LayoutRebuilder.ForceRebuildLayoutImmediate( [Layout-Group.RectTransform] );
(read more here)
请注意顺序很重要。
答案 1 :(得分:1)
设置TextMeshProUGUI
的文本后,textBounds
及其size
直到下一帧才更新。这是由Unity延迟的布局重建引起的。在他们的UI Layout Documentation中,其内容为:
重建不会立即发生,而是在当前结束时 帧,就在渲染发生之前。它不是立即的原因 是因为这可能会导致布局可能多次重建 在同一帧中,这会降低性能。
我将继续猜测GamePlay.GetHoverCanvas()
正在维护一个永不破坏的对象,因此,您的代码在所有情况下都可以正常工作,除了 首次运行。
可能有几种方法可以解决此问题,但最简单的方法是在设置text
和读取textbounds
的大小之间调用Canvas.ForceUpdateCanvases()
。它不是最快的功能,但应该可以解决问题。
另一种选择是代替一个同步功能,启动一个协程,该协程将text
设置为一帧,产生下一帧,然后在其第二个执行帧上读取textbounds
。 (这可能会导致尺寸弹出,并且看起来可能不受欢迎)。
答案 2 :(得分:0)
为避免需要强制更新Canvas,可以使用TextMeshProUGUI.GetPreferredValues()
提前确定当前分配给它的文本的宽度和高度。它将返回一个Vector2
。然后,您可以使用该Vector2
代替TextMeshProUGUI.textBounds
。
或者,如果您需要特定文本的大小而不实际分配它,请使用TextMeshProUGUI.GetPreferredValues(string text)
。
在给定宽度或高度限制的情况下,该方法还有其他重载方法。