[Unity]发包前遇到的坑之GridLayoutGroup
发包前禁用了UI上面一个调试页面A后,发现无法正确获取某一个用了GridLayoutGroup组件的所有子物体的世界坐标。
一顿研究之后发现,在Start的时候想要正确获取其坐标,需要强制刷新一次布局,方法如下:
UnityEngine.UI.LayoutRebuilder.ForceRebuildLayoutImmediate(this.GetComponent<RectTransform>());
至于为什么启用了调试页面A之后就能正确获取子物体的世界坐标,我猜是因为启用调试页面A后,整个预制体的Start时间变长,或者页面计算布局耗时更久,导致可以正确获取坐标。(有待验证)。
以下是在demo里总结的一些经验,非常容易理解,直接贴代码了。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestLayoutGroup : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
// 游戏第一帧无法直接获取GridLayoutGroup组件下子物体的世界坐标
Debug.Log("LayoutGroup: " + this.transform.position);
foreach (Transform transform in this.transform)
{
// 这里会连续打印多个相同的坐标
Debug.Log(transform.name + ": " + transform.position);
}
// 方法1:获取坐标前强制刷新布局ForceRebuildLayoutImmediate
// 这是一个静态方法,用于立即重建指定 RectTransform 上的布局,确保所有布局组件
// (如 HorizontalLayoutGroup、VerticalLayoutGroup、GridLayoutGroup)更新它们的子元素。
/* UnityEngine.UI.LayoutRebuilder.ForceRebuildLayoutImmediate(this.GetComponent<RectTransform>());
Debug.Log("LayoutGroup: " + this.transform.position);
foreach (Transform transform in this.transform)
{
Debug.Log(transform.name + ": " + transform.position);
}*/
// 方法2:在当前帧结束后再获取子物体坐标
//StartCoroutine(IEGetChildPosition());
}
IEnumerator IEGetChildPosition()
{
Debug.Log("LayoutGroup: " + this.transform.position);
yield return new WaitForEndOfFrame();
foreach (Transform transform in this.transform)
{
Debug.Log(transform.name + ": " + transform.position);
}
}
}
写到这里,发现yield return new WaitForEndOfFrame()未必靠谱,假如帧时间过长,这么处理可能未必可以正确获取到想要的坐标。
所以建议在获取坐标前先使用ForceRebuildLayoutImmediate强制刷新布局。