I have a bunch of UI gameobjects with nested child gameobjects that are set active and inactive depending on the dynamic content. What I find is that I always have to call LayoutRebuilder.ForceRebuildLayoutImmediate so that the layout is updated correctly after the hierarchy initialization is completed.
It’s very tedious, but it was at least working, until I noticed there is some unexpected side effect. When there are 2 sibling gameobjects X and Y, if X undergoing explicit ForceRebuildLayoutImmediate, and the other Y does not need any, the Y’s layout get updated too, and the scrollrect/scrollbar in Y gets reset. I think the problem is that both X and Y share a parent Horizontal Layout Group.
I want to redesign the UI structure so that I don’t have to keep calling ForceRebuildLayoutImmediate and suffer from side effects. Is there any one with experience in dealing with this quirking behavior?
Thanks.
This is what I am using at the moment
public class UIBase : MonoBehaviour {
public UnityEvent LayoutRebuildEvent;
public virtual void Init(object args) {
// at this point, this gameobject is inactive
// ... init content
// show some gameobject and hide some game objects
// m_gameObjectA.SetActive(true);
// m_gameObjectB.SetActive(false); etc.
}
public void Show() {
this.gameObject.SetActive(true);
}
void OnEnable() {
// this is triggered by Unity, due to this.gameObject.SetActive(true)
StartCoroutine(_OnEnable());
}
IEnumerator _OnEnable() {
yield return new WaitForEndOfFrame();
// bubble the layout event up to the parent
// parent will then call ForceRebuildLayoutImmediate() on children then itself (sequence is important)
// which will propogate the force layout up the tree from grand-grand-child to grand-child to child to parent etc.
RequestLayoutRebuild();
}
public virtual void ForceRebuildLayoutImmediate() {
if(this.gameObject.activeSelf) {
LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)transform);
}
}
protected void RequestLayoutRebuild() {
LayoutRebuildEvent?.Invoke();
}
}