I am having a problem with my layout groups and keeping my UI consistent. I have a menu that holds two empty elements Blue and Green boxes bellow that get filled at playtime depending on what the player does. The orange boxes are buttons that may add or remove both purple boxes or orange boxes depending on the button pressed. The Gray, Blue, and Green boxes all have Vertical Layout Group and Content Size fitter (vertical fit set to "Prefered Size"). So from my understanding, all children within these boxes should be stacked vertically and will expand and contract the box as needed.
The problem I am having is that the first time I press a button that adds a purple box and expands the blue box, the green box stays where it is. The second time I press a button the Green box shifts where it should be no matter what gets added to the blue box. Conversely if pressing a button for the first time removes purple boxes and contracts the blue box, the green box stays where it is until I press a button again then shifts where it should be.
If I manually change any of the Gray, Blue, or Green boxes attributes such as anchor pivot or scale the boxes rearrange themselves the way it should be.
Am I doing something wrong with Vertical Layout / Content Size fitter? I hope this is enough to go on. I can provide code if need be. I just don't know exactly what to share.
When the button is pressed call this method.
void AcceptUnlockButtonInput(Exit roomExit) {
if (PlayerHasKeyForExit(roomExit)) {
LogAction(roomExit.exitUnlockDescription);
roomExit.attemptedToExit = false;
roomExit.attemptedToUnlock = false;
} else if (roomExit.attemptedToUnlock == false) {
LogAction(roomExit.exitLockedDescription);
}
DisplayActionText();
foreach(Transform child in inputContainer.transform) {
Destroy(child.gameObject);
}
DisplayInputButtons();
Canvas.ForceUpdateCanvases();
}
LogActrion() just simply adds a string to a list then DisplayActionTest() reads off that list and creats/adds gameObjects to the container.
public void DisplayActionText() {
actionLog.ForEach(value => {
var textObject = Instantiate(displayTextPrefab) as GameObject;
var textMeshPro = textObject.GetComponentInChildren<TextMeshProUGUI>();
textMeshPro.text = value;
textObject.transform.SetParent(outputContainer.transform, false);
});
actionLog.Clear();
Canvas.ForceUpdateCanvases();
}
Simply creats a button for each exit and adds the original method to the buttons listener.
public void DisplayInputButtons() {
foreach (var exit in Exits) {
var unlockButton = Instantiate(userActionButton) as GameObject;
newButton.text = buttonText;
newButton.transform.SetParent(buttonGroup.transform, false);
unlockButton.onClick.AddListener(() => AcceptUnlockButtonInput(exit));
}
}
