SceneManager is not working as expected

Hey guys.

Iam working on a version of Block Breaker so Iam posting my question here:

Iam trying to make a splash screne that fades in and out. In the Unity course everything was just fine and dandy, but I upgraded my project to Unity5 and Iam having some issues with the fade in / fade out thingy.

Unity5 does not use Application. anymore. Instead it uses SceneManager. Now I want my splash screne to load the next level(screne) once it fades out. My code:

void Update () {

        if(Time.timeSinceLevelLoad < timeToFade){          
          //  FADE IN
        }else{
            gameObject.SetActive(false);
        }

        bool splashPanel = (this.tag == "SplashPanel");

        if(splashPanel){
            gameObject.SetActive(true);
            Invoke("FadeOut",2.5f);
            int indexSC = SceneManager.GetActiveScene().buildIndex;
            SceneManager.LoadScene(indexSC+1);

The problem here is that when I press play, the next scene loads right away. There is no splash screne to be seen. And it doesn’t even invoke the loading. Why does half the code get ignored and how can I solve this so its working the way I want it.

Many thanks!

1 Like

Hey Rok,
There is nothing delaying the call for changing the scene, you could put it inside an Invoke with a timer in the Start method() instead of in the update

1 Like

I’am not sure how this would work. Start() gets called only once. My fadein and fadeout methods need to be called multiple times to work. Or is there something fundamentally different in Unity5?

Im saying about the

Int indexSC
SceneManager.LoadScene

You can keep the fade in the update and call the invoke to change the scene in the Start method

void Start() is only called once, when the GameObject start in the scene, and void Update() is called once per frame. So it is good to avoid putting too many methods inside the Update when it is possible, it can be very heavy to write things under the Update, causing performance problems.

I had a similar requirement recently where I wanted to load the scene after something else had occured and not before.

I created a LazyLoadScene() method which would start a coroutine for the amount of time and then go on to load the required scene.

/// <summary>
/// Loads a scene for the specified name but with a delay
/// </summary>
/// <param name="name">The name of the scene to load</param>
private void LazyLoadSceneAsync(string name)
{
    StartCoroutine(DelayedLoadSceneAsync(name));
}


/// <summary>
/// Delays the loading of the specified scene
/// </summary>
/// <param name="name">The name of the scene to load</param>
private IEnumerator DelayedLoadSceneAsync(string name)
{
    yield return new WaitForSeconds(_sceneEndingDelayDuration);

    LoadSceneAsync(name);
}


/// <summary>
/// Loads a scene for the specified name
/// </summary>
/// <param name="name">The name of the scene to load</param>
private void LoadSceneAsync(string name)
{
    SceneManager.LoadSceneAsync(name);
}

The above should be fairly self explanatory, the things you may need to change are perhaps the scene name to a scene index build id and also replace the _sceneEndingDelayDuration in the DelayedLoadSceneAsync method with the duration of your fade. Initially you could just set that to 2.5f but it may be more beneficial to pass the value to the method or set it more globally to provide re-usability of these methods.

As @Joao_Dalvi mentioned, where possible it would be best to not cram too much code directly into the Start() and Update() methods, you could refactor your code so that you call private methods instead from either Start() or Update(), this would increase the readability and make it more maintainable going forwards.

Hope this helps.

3 Likes

Okay, cool. Thanks to both. I didn’t understand at first what Joao ment but it makes sense now.
The code looks reasonable, thanks ! :sunny:
Iam still confused though as to why my code behaves the way it does. Man, I hate switching software…:cold_sweat:

In layman’s terms you are basically saying…

Start a fade and now load the next scene

where-as what you want to say is…

Start a fade, wait until the fade has completed, then load the scene

The lines of your code fire one after the other without anything in the middle to say “wooah, hold on a sec, we are still in the middle of a fade here”

Hope this helps :slight_smile:

2 Likes

Yes, It does.
I will have to revisit my code as it seems because this used to work in Unity4. Maybe I overlooked something.

Anyway, thank you for your time.

1 Like

Rok,
Sorry for not being clear enough. English is not my main language, sometimes I think in portuguese and write in english, which causes a few cohesion problems.
@Rob gave a very good explanation, let us know if you got this script running as it should or not. Btw @Rob, I use this exact same code of yours for dalaying the loadscene (with diffetent names), works very well!

1 Like

It is far better than a lot of people I know for whom English is their first language :slight_smile:

I think it is fair to say that we rock @Joao_Dalvi - at least until proven other wise :wink:

Just to add, I changed two of the methods to Private in the above example purely for @Rok_Slana to implement more easily. In the app I took it from, it’s part of a GameManager class which has LazyLoadSceneAsync and LoadSceneAsync set to Public so that the functionality can be used in many places, it also enables me to choose whether I want a scene to be loaded lazily or immediately by using the appropriate method.

1 Like

Exactly!! I was thinking the same thing :joy:

Mine is public too, I was thinking about setting the LevelManager class methods to static, so I don’t need to look for it anymore, what do you think?[quote=“Rob, post:11, topic:9315”]
It is far better than a lot of people I know for whom English is their first language
[/quote]
Thank you, by the way

1 Like

Potentially a good idea, obviously it may depend on what else it is doing, e.g. if there are any scenarios where you have to actually instantiate it in order to perform a task. Would also need to consider whether it was appropriate for it to be available across the entire application - or, just the things that need to know about it :slight_smile:

1 Like

Thats true, I don’t know how having some public static across the project Influences the performance of the application. Glitch garden, for example, has a couple of gameobjects that have to access the LevelManager, but I dont know if it is better performance wise to just look for the LevelManager on those GameObjects or to declare it as static.

Another thing that I was wondering, isn’t worth performance wise to create a GameObject that cashes the references of all other GameObects? Instead of having to find a couple of GameObjects wiithin the script that have to access them, we could cash just the one that have the reference to all the others, and use those references?
I dont know if it is too much of a crazy idea.

I think there may need to be a stronger argument for making the class static other than just the ability to reduce the number of calls to find it etc. You would be effectively making a utility class. For me I tend to focus initially on locking everything down first, trying to ensure that nothing is exposed via Public that doesn’t need to be. Creating the utility/helper classes tends to come a little later once I’ve spotted that I am re-using similar functionality, the trick then is to ensure that you make the solutions generic so that you can pass in specific values/objects to produce the desired result.

Regarding the One Ring to Rule The All approach with the GameObject, I’m not sure about that, it doesn’t feel quite right.

I hear what you are trying to do, e.g. load up one object with references to everything and then boom - make calls to that, but, in doing so, references to a lot of objects I don’t need in every scene have to be created. For example, my Game Over scene may just have a UI.Text object which is set to “Game Over” and have a button to play again, it wouldn’t make a lot of sense that my initial Start scene were aware of those components, as it won’t interact with them.

To me, it feels like if that were the way to go about it you would see that approach in lots of (if not all) examples when you browse the web for Unity, and I haven’t so far.

Things knowing about the things they need to know about is the approach I typically take.

1 Like

Thank you for your reply Rob,

I’m still a little lost about when I should be using public static classes, if there is any situation that I should use it. Perhaps a good use to those is only when I have a variable/method that should share the same value across different instances and that I need the value to be accessed by outside elements

It makes sense, perhaps it would be better to stick to type specific controller classes instead of ones that can control everything, it may cause fewer problems when treating exceptions and situations that diverge from the standard scope that a global controller would be created to. The tip regarding making solutions as generic as possible to help passing values is a good one, I had some problems on my last project for not doing this.

NOO!! Forget everything discussed so far! I need an GameObject with that name!! “One Ring to Rule Them All” :heart_eyes:
:joy:

I agree to that, this is an important approach! I also presume that most of the good Idea that pops up has already been thought by someone else and there is a good chance that it is already in the internet, and usually I’m able to find it just to find out t it it is already an developed idea, sometimes I’m able to learn a lot of new things and sometimes they are very useful!!

1 Like
using UnityEngine;
using JRRTolkien;

namespace Mordor.MountDoom
{
    class TheOneRing
    {
        static TheOneRing _theOneRing = null;

        private RingBearer _ringBearer = null;

        private void Awake()
        {
            if (_theOneRing != null)
            {
                Destroy(gameObject);
            }
            else
            {
                _theOneRing = this;

                GameObject.DontDestroyOnLoad(gameObject);
            }
        }


        public RingBearer Bearer
        {
            get { return _ringBearer; };
        }

        public void Travel()
        {
            // TODO:
        }

        public void TurnBearerInvisable(ref RingBearer ringBearer)
        {
            // TODO:
        }

    }
}

:wink:

if (_theOneRing != null)
{
      Destroy(gameObject);
}

:joy::joy::joy::joy:

1 Like

Been away for a few days now for the holiday. This morning I resumed working on this problem and I got this thing working. Thank you both for help, especially to you Rob for the code.

I must add that I did have to fight it a bit. But not so much for the code than for the Unity not being in good mood today. Maybe I run it too early in the morning or something :slight_smile: Looks like I need more adjusting to Unity5.

Away I go now implementing AdMob plugin and stuff…:sweat_smile:

2 Likes

Glad it’s all working for you now @Rok_Slana :slight_smile:

Privacy & Terms