【Unity】LayoutGroupを手動更新する

概要

LayoutGroupとは、リストを作るときによく使用するVerticalLayoutGroupなどのベースクラスのことです。

LayoutGroup以下にコピーしたオブジェクトを配置したりすると、どうしても一瞬位置更新が遅れてちらついて見えます。

このちらつきをなくすために、オブジェクト追加直後に強制的にLayoutGroupを更新させます。

動作検証

どのタイミングで更新されるのかを確認するため、以下のコードを用意しました。

using UnityEngine;
using UnityEngine.UI;

public class Test : MonoBehaviour
{
    [SerializeField] private GameObject copy = null;

    // Start is called before the first frame update
    void Start()
    {
        GameObject gameObject = GameObject.Instantiate(copy);
        gameObject.transform.SetParent(copy.transform.parent);
        gameObject.SetActive(true);
        RectTransform rectTransform = gameObject.GetComponent<RectTransform>();
        LayoutGroup layoutGroup = this.GetComponent<LayoutGroup>();
        Debug.Log("1 " + rectTransform.anchoredPosition);
        layoutGroup.SetLayoutHorizontal();
        layoutGroup.SetLayoutVertical();
        Debug.Log("2 " + rectTransform.anchoredPosition);
        layoutGroup.CalculateLayoutInputHorizontal();
        layoutGroup.CalculateLayoutInputVertical();
        Debug.Log("3 " + rectTransform.anchoredPosition);
        layoutGroup.SetLayoutHorizontal();
        layoutGroup.SetLayoutVertical();
        Debug.Log("4 " + rectTransform.anchoredPosition);
    }
}

このコードを実行した結果が下記になります。

1 (-267.0, -539.0)
2 (-267.0, -539.0)
3 (-267.0, -539.0)
4 (50.0, -50.0)

この結果から「CalculateLayoutInputHorizontal、CalculateLayoutInputVertical」の後に「SetLayoutHorizontal、SetLayoutVertical」を実行することで位置更新されることがわかりました。

なぜ「CalculateLayoutInputHorizontal、CalculateLayoutInputVertical」が必要なのか

LayoutGroupはプライベートメンバ変数に「List<RectTransform> m_RectChildren」を持っており、「SetLayoutHorizontal、SetLayoutVertical」で位置更新をするときはm_RectChildren内のオブジェクトに対して行います。

先ほどの検証の「1」「2」の時点では作成したオブジェクトがm_RectChildrenに登録されていませんでした。

そのため、「CalculateLayoutInputHorizontal、CalculateLayoutInputVertical」を使ってm_RectChildrenを更新する必要があるのでした。

結論

LayoutGroupを更新するのに必要なコード下記になります。

layoutGroup.CalculateLayoutInputHorizontal();
layoutGroup.CalculateLayoutInputVertical();
layoutGroup.SetLayoutHorizontal();
layoutGroup.SetLayoutVertical();
   

コメントを残す


CAPTCHA