0
votes

I'm attempting to make a level select that requires as little upkeep as possible as I intend on adding updates to add more levels (Unity Scenes) in unity.

To account for this I'm attempting to get the level select to create buttons for each level in the Unity Build settings, and then create a template object from a prefab in which it can map buttons it creates onto.

I have it mostly working, but for some reason, it's mapping the buttons in the wrong order, I'm trying to go down to up and Unity appears to be grabbing the Gameobjects is a random order.

Here is my code:

    private Scene[] levels;
    private int currentButtonId = 1;   

    public Transform buttonsHolder;
    public GameObject buttonPrefab;
    public GameObject buttonSlotsPrefab;

    private GameObject[] levelButtonSlots;
    private int currentLevelSlot = 0;
    private int numSlotsToMove = 0;

 private void Start()
    {            
        var sceneCount = SceneManager.sceneCountInBuildSettings;
        levels = new Scene[sceneCount];
        for (var i = 0; i < sceneCount; i++) 
        {
            // Beginning Setup
            levels[i] = SceneManager.GetSceneByBuildIndex(i);

            // Look for Level Placement Slots
            levelButtonSlots = GameObject.FindGameObjectsWithTag("Level Slot");

            // If there aren't enough Level Placement Slots make more by creating a template
            if(levelButtonSlots.Length < levels.Length)
            {
                GameObject buttonSlots = Instantiate(buttonSlotsPrefab);
                buttonSlots.transform.position = new Vector2(0, 10 * numSlotsToMove);
                numSlotsToMove++;
            }
            // Go get those new placement slots
            levelButtonSlots = GameObject.FindGameObjectsWithTag("Level Slot");

            // Create Button
            GameObject currentButton = Instantiate(buttonPrefab, buttonsHolder);
            // Move it to the next slot
            currentButton.transform.position = levelButtonSlots[currentLevelSlot].transform.position;
            currentLevelSlot++;

            // Add Text to a new button
            TextMeshProUGUI buttonText = currentButton.GetComponentInChildren<TextMeshProUGUI>();
            buttonText.text = (currentButtonId.ToString());

            // Setup what which scene clicking a button will do
            ButtonManager buttonScript = currentButton.GetComponentInChildren<ButtonManager>();
            buttonScript.sceneToLoad = currentButtonId;

            currentButtonId++;
        }             
    }

The buttonsHolder variable is set in the editor and is the canvas. The buttonPrefab is a TextMeshPro button prefab I set in the editor, it has the level Buttons tag and a simple script that loads the specified scene when clicked. And the buttonSlotsPrefab is a gameobject prefab that I set in the editor, it has the Button Placement Slot tag and it contains 8 other empty gameobjects each with the level slot tag, I use these 8 objects as the guides as to where the buttons should be placed on runtime.

Again, my goal is to place the buttons going from bottom to top, but instead, Unity spits out this on runtime for no apparent reason:

I'm sorry about the naming convention some variables have, I'm tired and stressed as I've been at this 2 two days straight. I will fix those up once I get things working.

After further testing, I have noticed that when I first create buttonSlotPrefab, everything works perfectly, however, after restarting Unity (Not changing any files) when I run the game again after a restart the order gets randomized. Could this be a bug in the Unity Engine?

1
sort them by positional value? is it because thats the order in the heirachy? - BugFinder
hard to say exactly how to sort but you just need to sort your array of game objects after you call find game object with tag - vasmos
@BugFinder You would think so, but I've checked a dozen times to make sure they are in the right order and they are, I've added a section to my OP to explain something new I've encountered which might affect things. - Jhon Piper
@vasmos I know you said it's hard to say how you would sort the array after looking for the tags but can you think of any way? It may be a final resort. - Jhon Piper
post the code for the script attached to levelButtonSlots - vasmos

1 Answers

1
votes

If i understant your problem, you have a problem between number of button and slot: you have slot spaced on axis y and you havent always the levelsolt[0] at the bottom of screen, so

you could order (ascending or descending i dunno) the levelslot on y axis before creating button: i am using Linq so add using System.Linq;

if (levelButtonSlots.Any())//Same thing than levelButtonSlots.Length > 0
{
    levelButtonSlots = GameObject.FindGameObjectsWithTag("Level Slot").OrderBy(go => go.transform.position.y).ToArray();
}

or

    levelButtonSlots = GameObject.FindGameObjectsWithTag("Level Slot").OrderByDescending(go => go.transform.position.y).ToArray();

I have added a test if no value in array, but maybe the error doesnt exist, i havent tested that