UI LayoutGroup does not organize dynamically instantiated buttons

I have a UI panel with a vertical layout group component and a content size fitter.
When I hit play and instantiate the button prefabs, their positioning is not affected by the layout group component. I can see that they are being instantiated as expected, but the layout group doesn’t seem motivated to organize them unless I manually resize the screen, or re-order the siblings while the game is paused.

Code sample:

void InstantiateNametags()  
	{
		VerticalLayoutGroup layoutGroup = hud_left.GetComponentInChildren<VerticalLayoutGroup>(); // Finds the left-side Roster panel.
		layoutGroup.childAlignment = TextAnchor.UpperLeft; // Ensures the names will be left-aligned.

		foreach (GameObject fighter in combatantsRosterP1)
		{
			GameObject nametag = GameObject.Instantiate (nametagPrefab) as GameObject;
			nametag.transform.SetParent(layoutGroup.transform, false); // <-- HERE, I suspect, is the culprit.
			nametag.GetComponentInChildren<Text>().text = fighter.name;
			// Additional button functionality here

		}
		layoutGroup.gameObject.GetComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize; 

		// Code repeats for the right-side hud/roster.

	}

How can I gently remind the layout group to perform its function before the player sees disorganized buttons?
Could this have to do with the fact that I am using transform.SetParent() rather than accessing the RectTransform component?

Setting the contentsizefitter verticalFit to preferred size (from unconstrained) after creating the buttons was an attempt to fix this issue, as the rect’s height was being set to zero without content, but I’m not sure the content size fitter is part of the issue anymore…

I know this is an old thread, but for anyone still wanting an answer you can force a LayoutGroup to recalculate if you call LayoutRebuilder.ForceRebuildLayoutImmediate(_rootRectTransform); where “_rootRectTransform” is the RectTransform on the Gameobject that contains the LayoutGroup component (or any parent in the hierarchy above it).

This method essentially “refreshes” the root RectTransform and all it’s children, which forces the LayoutGroup to recalculate where each of its elements should be.

Try adding a LayoutElement compoment to your new objects

		LayoutElement layout = nametag.AddComponent<LayoutElement>();
		layout.minHeight = 100f;
		layout.preferredWidth = 600f;
		layout.preferredHeight = 100f;
		layout.flexibleHeight = 0;

I don’t know if it’s the same issue but I’ve encountered something similar as has this person;

http://answers.unity3d.com/answers/1066088/view.html

I’ve posted a response to that question which could help.

I’m not at my pc atm but have you tried Canvas.ForceUpdateCanvases()?

If that doesn’t work check if layoutgroup has a public function you could call named somewhat like ForceUpdate().

I had a somewhat similar problem with inputfields not updating the visible text when adding characters through code. The line would get longer than the inputfield having characters disappear instead of the field scrolling with the caretposition. Some sort of forceupdate function fixed that for me.

Use RectTransform.SetAsFirstSibling() or RectTransform.SetAsLastSibling() after adding new elements. This will reorganize the LayoutGroup properly.

I came cross the same problem, my solution:

Short answer:
call LayoutRebuilder.ForceRebuildLayoutImmediate(root rect transform); after you have changed something inside dynamically calculated groups.

I’ve been struggling for a while with this a long time, usually doing workarounds like using coroutines and wait for the next frame (or a couple of frames) to be sure my new layout is recalculated.

Someone goes with Canvas.ForceUpdateCanvases() but this is rather expensive.

What worked for me: Instantiate the object then set its parent at the end of the frame:

GameObject newGameObject = Instantiate(
     prefab,
    new Vector3(),
    Quaternion.identity
);

// set parent is done at the end of frame to force re-calculate layout
StartCoroutine(SetTransformParent(newGameObject ));

private IEnumerator SetTransformParent(GameObject newGameObject){
    yield return new WaitForEndOfFrame();
    RectTransform rectTransform = (RectTransform) newGameObject.transform;
    rectTransform.SetParent(someGameObject);
}