0
\$\begingroup\$

the code below is the code I use to load my game scene ater the intro animation plays. The way it works is that it preloads the game scene because it is big enough it takes time to load and activates it after 15 seconds.

I want to use this code in a similar manner for my main menu, but instead of preloading and waiting for seconds I want it to preload and wait for UI button.

public class IntroToForest : MonoBehaviour
{
    public float WaitToLoad = 14.0f;

    void Start()
    {
        StartCoroutine(LoadScene(WaitToLoad));
    }

    IEnumerator LoadScene(float WaitToLoad)
    {
        yield return null;
        AsyncOperation asyncOperation = SceneManager.LoadSceneAsync("Forest Map");
        asyncOperation.allowSceneActivation = false;

        while (!asyncOperation.isDone)
        {
            if (asyncOperation.progress >= 0.9f)
            {
                yield return new WaitForSeconds(WaitToLoad);
                asyncOperation.allowSceneActivation = true;
            }
            yield return null;
        }
    }
}

Side note: I incorporated DmGregory's answer into my menu controller script and got this:

public class MenuController : MonoBehaviour
{
    public string SceneName;

    AsyncOperation preload;

    void Start()
    {
        preload = SceneManager.LoadSceneAsync(SceneName);
        preload.allowSceneActivation = false;
    }
    public void Go_to_game()
    {
        if (preload.progress < 0.9f)
        {
            if (PlayerPrefs.HasKey("HasSeenIntro"))
            {
            preload.allowSceneActivation = true;
            }
            else
            {
                PlayerPrefs.SetInt("HasSeenIntro", 1);
                SceneManager.LoadScene("Intro");
            }
        }
    }
}

The problem is that the UI button will not work.

\$\endgroup\$
8
  • \$\begingroup\$ @DMGregory I changed the question so it should be easier to understand. \$\endgroup\$
    – Ethan K-B
    Commented Aug 9, 2019 at 19:18
  • \$\begingroup\$ Can you clarify the actual problem part? Is it that you essentially want to also wait for a button press at the end? \$\endgroup\$
    – House
    Commented Aug 9, 2019 at 21:38
  • \$\begingroup\$ @MichaelHouse Basically the script I posted will wait to a set amount of time to load the scene. I want it to rely on a ui button being pressed instead of a timer. \$\endgroup\$
    – Ethan K-B
    Commented Aug 9, 2019 at 21:41
  • \$\begingroup\$ So, you wait until it's 90% loaded, then as long as it's still not loaded, wait 14 seconds each time you check. Instead, you want to go to 90% and then wait for a button press? Ah I see, you're using the example: docs.unity3d.com/ScriptReference/… \$\endgroup\$
    – House
    Commented Aug 9, 2019 at 21:51
  • \$\begingroup\$ You did not implement the answer correctly. allowSceneActivation = true should not be gated by your progress check, otherwise you skip transitioning to the scene if it's not already loaded when the button is clicked. \$\endgroup\$
    – DMGregory
    Commented Aug 10, 2019 at 23:28

3 Answers 3

2
\$\begingroup\$

Rather than running this as a coroutine, ticking every frame waiting to see if the button is pressed, I'd just store the AsyncOperation and let the button give it a kick when the player finally presses it.

public class ScenePreloader : MonoBehaviour {

    public string sceneName;

    AsyncOperation preload;

    void Start() {
        preload = SceneManager.LoadSceneAsync(sceneName);
        preload.allowSceneActivation = false;
    }

    // Call this from your UI button.
    public void BeginTransition() {
        preload.allowSceneActivation = true;

        if(preload.progress < 0.9f) {
            // Here, you might want to display a loading spinner,
            // so you have coverage if the user is very fast / load is slow.
        }            
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ Is there a way to do this with 2 scenes? \$\endgroup\$
    – Ethan K-B
    Commented Aug 10, 2019 at 19:34
  • 1
    \$\begingroup\$ That sounds like a different question than the one you've asked above. The tricky bit is there's no way to cancel an asynchronous scene load that I know of, so safely disposing of preloaded scene A when the player has decided to go to preloaded scene B instead could require some extra work. \$\endgroup\$
    – DMGregory
    Commented Aug 10, 2019 at 19:40
1
\$\begingroup\$

Just use a boolean flag.

public class IntroToForest : MonoBehaviour
{
    public bool buttonPressed = false;

    void Start()
    {
        StartCoroutine(LoadScene("Forest Map"));
    }

    IEnumerator LoadScene(string scene)
    {
        AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(scene);
        asyncOperation.allowSceneActivation = false;

        while (!asyncOperation.isDone)
        {
            if (asyncOperation.progress >= 0.9f)
            {
                if(buttonPressed)
                    asyncOperation.allowSceneActivation = true;
            }
            yield return null;
        }
    }
}

Configure your button in the Inspector to set buttonPressed to true when pressed.

\$\endgroup\$
1
  • \$\begingroup\$ MichaelHouse Nothing Happens when I press the button. \$\endgroup\$
    – Ethan K-B
    Commented Aug 10, 2019 at 21:11
1
\$\begingroup\$

You can use WaitWhile to define a condition for the coroutine's yield. Something like this could work, with a button configured to update the value of buttonPressed accordingly.

public class IntroToForest : MonoBehaviour
{
    public bool buttonPressed;

    void Start()
    {
        StartCoroutine(LoadScene());
    }

    IEnumerator LoadScene()
    {
        AsyncOperation asyncOperation = SceneManager.LoadSceneAsync("Forest Map");
        asyncOperation.allowSceneActivation = false;

        while(!asyncOperation.isDone)
        {
            yield return new WaitWhile(() => !buttonPressed);
            if (asyncOperation.progress >= 0.9f)
            {
                asyncOperation.allowSceneActivation = true;
            }
        }
    }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .