- Home /
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...
The parent 'Roster' gameObject is being instantiated during Start(), immediately before the buttons are being instantiated - I tried using
Invoke("InstantiateNametags", 0.1f);
rather than calling InstantiateNametags() right away, and this has "solved" the problem - though I can't help but feel that there may be a better solution. Shouldn't I be able to instantiate the layoutGroup gameObject, then instantiate some content, and have the layoutGroup recognize what needs to be done?
Answer by steven_scottyd · May 11, 2020 at 12:41 PM
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.
Answer by ilya_ca · Oct 27, 2016 at 10:30 PM
Use RectTransform.SetAsFirstSibling() or RectTransform.SetAsLastSibling() after adding new elements. This will reorganize the LayoutGroup properly.
As a beginner reading this response, it is not detailled enough. Calling only "RectTransform.SetAsLastSibbling()" does not bring the last instanciated object on top.
In my case, buttonInstance.transform.SetAsLastSibbling(); does not bring the UI element to the front and I end up dragging (and dropping) elements under their slots/place holders.
Answer by David_Biggs · Feb 27, 2015 at 02:40 AM
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;
Thanks for the suggestion, I gave it a shot just now (without my 'invoke' fix); not only did the layout group not organize the elements, but the preferredWidth, preferredHeight etc traits did not update! When I altered the screen size / reordered the siblings (with the game running), the 'new' width and height then updated.
Answer by Guy-Corbett · Sep 13, 2015 at 02:04 PM
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.
@Guy Corbett As has been mentioned, this page seems to have gone awol... Any chance of a hint of what was covered? I'm having much the same problem and can't find a solution. Thanks
Not sure what happened there. I think this is the right link;
Thanks! sadly not the answer for me but much appreciate your quick response :)
Answer by Curb · Feb 24, 2016 at 08:53 AM
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.
Your answer
Follow this Question
Related Questions
How do I layout dynamically instantiated UGUI components? 1 Answer
How to Save Property Values of a Component on a Scriptable Object? 1 Answer
Instantiating UI element on Screen space - Overlay not instantiating exact specified location 0 Answers
Is there a way to Instantiate a button prefab as a child of a Canvas? 2 Answers
Layout Group not working when instantiate from prefab 1 Answer