1
\$\begingroup\$

I'm using this line of code to select my level, and currently I have different scenes for each levels. I want to be able to reuse the same scene to change levels as well but I don't know how, here's the line:

button.GetComponent<Button>().onClick.AddListener(() => Levels("Level " + button.levelText.text));

Since I'm using string to load my scene with the function below:

void Levels(string value)
{
    SceneManager.LoadScene(value);
}

I really wish I could use prefab name instead the scene name and I don't want to have 20 scenes for it. Any help would be appreciated.

\$\endgroup\$
  • \$\begingroup\$ What do you mean by "use prefab name instead the scene name"? What prefab? \$\endgroup\$ – zcabjro Nov 24 '16 at 10:45
  • \$\begingroup\$ I made an array and I drag the prefabs(levels) in the inspector in the game scene. Currently I have three level prefabs and I want to be able to instantiate the prefab that I have selected in level selection scene to be loaded to the game scene, and I want to use their name instead of the array index.. is it possible? \$\endgroup\$ – user3132527 Nov 24 '16 at 11:00
  • \$\begingroup\$ What is stopping you from instantiating the selected prefab and destroying whatever you're using for level selection? You then have one scene but the user selects the content to be instantiated. \$\endgroup\$ – zcabjro Nov 24 '16 at 11:18
  • \$\begingroup\$ I'm using a list for my button prefab and I'm using an array for my level prefab, now I don't know how to load the level prefab based on the level button that I have click in the level selection scene. \$\endgroup\$ – user3132527 Nov 24 '16 at 11:28
  • 1
    \$\begingroup\$ Have you considered assigning the buttons a number (such as the order in which they appear) and using that number to index into your array of prefabs? \$\endgroup\$ – zcabjro Nov 24 '16 at 12:08
1
\$\begingroup\$

Have a look at Resources.Load(). To work properly, the prefab must be in a folder called "Resources", and you load it by its filename (not including "Resources/" or ".prefab").

Use it like this:

GameObject nextLevel = Resources.Load<GameObject>("Levels/Level2");
\$\endgroup\$
  • \$\begingroup\$ Thank you for the quick reply but if I have 20 levels, I have to write 20 lines of this code above? \$\endgroup\$ – user3132527 Nov 24 '16 at 9:04
  • \$\begingroup\$ Sorry for my late response. You can use a parameter for the level name or ID. Since you're already creating the button click handler dynamically (in the code you originally posted), just change your Levels function to load a prefab based on the name you pass in. (If your prefabs are Level01-Level20, use something like string.Format("{0:D2}", id) to get them to have correct padding.) \$\endgroup\$ – piojo Nov 28 '16 at 5:50
1
\$\begingroup\$

In order to associate a button press with an index into your array of prefabs, you could create something like the following:

public class LevelLoader : MonoBehaviour
{
    public Object[] levelPrefabs;

    public void Load(int levelIndex)
    {
        if (levelIndex >= 0 && levelIndex < levelPrefabs.Length)
        {
            Instantiate(levelPrefabs[levelIndex]);
        }
        else
        {
            Debug.LogError("Invalid level index: " + levelIndex);
        }
    }
}

By adding this to a GameObject in your scene, you can register the Load method to the OnClick event and pass in the appropriate level index.

One further readability improvement could be to use an enum instead of plain ints:

public class LevelLoader : MonoBehaviour
{
    public enum Level
    {
        Tutorial,
        Level1,
        Level2,
        FinalBoss
    }

    public Object[] levelPrefabs;

    public void Load(Level level)
    {
        int levelIndex = (int)level;
        if (levelIndex >= 0 && levelIndex < levelPrefabs.Length)
        {
            Instantiate(levelPrefabs[levelIndex]);
        }
        else
        {
            Debug.LogError("Invalid level index: " + levelIndex);
        }
    }
}

This just ensures that in the editor you are using readable values, so is less error-prone (still no guarantee that your array is correctly setup).

\$\endgroup\$
  • \$\begingroup\$ What about unloading the old level? I don't see how a single game object would constitute an entire level and I think the OP is better looking into SceneManager.LoadSceneAsync(Additive). \$\endgroup\$ – Droppy Nov 25 '16 at 11:25
  • \$\begingroup\$ @Droppy Personally, I agree with you. However, there is a school of thought, within the Unity developer community, that prefers 'filling in' a single scene, instead of creating many different ones. One immediate problem is build size, since the existence of the levelPrefabs will prevent Unity from excluding prefabs that are never used. Nonetheless, there are reasons this is desirable in some situations and the OP has led me to believe this is what they are asking for. Crucially, I am demonstrating the link between button and array index: what the OP does from there is up to them. \$\endgroup\$ – zcabjro Nov 25 '16 at 11:32
0
\$\begingroup\$

Sorry for being this late but I already solved it, here;s how I've done it

void Levels(string value)
{
    CreateLevel.currentLevel = int.Parse(value);
    SceneManager.LoadScene(1);
}

Since I'm using my

button.levelText.text

to assign each buttons, I just convert the

string value

to integer

And call the static int

currentLevel

from this script

public GameObject[] Levels;
public static int currentLevel = 0;

void Start () {
    GameObject obj = Instantiate(Levels[currentLevel-1]) as GameObject;
}

and I just drag the prefabs into the inspector so when I click on the button with certain number, it will load the prefab with the same index number as the text on the button from previous scene.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.