0

I would like to populate the UI when I load a scene, with the correct data, instead of placeholders.

When I call "LoadSceneAsync", what would be the first object that is called, so I can fill the UI label with the correct data? I know that there is a scene GameObject, but I am not sure if that would fit my needs.

I am looking for some sort of constructor, called when a new scene object is loaded; to plug in my setup function.

3 Answers3

2

You say

Indeed I did use "onlevelwasloaded" but the UI element may not be there, ready to go, when I invoke it, which lead to errors

That would be an incredibly sever bug in Unity! :)

Could it be that you are mixing-up Awake and Start somewhere?

One way to think of it is once you call Start, you know all the Awake have already run.

When I call "LoadSceneAsync", what would be the first object that is called, so I can fill the UI label with the correct data

You are still within the same frame.

Once you see LoadSceneAsync you can be absolutely assured everything is Awake 'd.

Or indeed once you use Start you can be absolutely assured everything is Awake 'd.

1) could it be that in some of your UI elements (or whatever) you are doing something in Start which you should do in Awake?

2) if (for some reason) you want to "wait until the next frame", perhaps just during development - then do that, wait a frame. You'll see a flicker, but if that's what you want to do (for some reason) do that.

3) note that if you mean you want to go to the net to get something, well of course you have to wait frames (use Update/coroutine) until the information comes back from the net, obviously. (How else could it be?)


Note that in practice, one should be using UnityEngine.Events.UnityEvent everywhere.

Fattie
  • 27,874
  • 70
  • 431
  • 719
1

Maybe this is what you are looking for http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnLevelWasLoaded.html

Sushant Poojary
  • 353
  • 4
  • 12
0

Relying on Unity internal functioning is not always the way to go. Particularly when dealing with RESTApi (which is somehow what you are dealing with here).

You cannot assume one object will be ready before another except if you control it.

Add a Controller script that uses Awake. In the Awake, call all the methods you are needing and use some callback to generate secondary code when primary is ready.

public class MyController: MonoBehaviour{

    private ServerRequestController serverCtrl = null;
    private UIController uiCtrl = null;
    private void Awake(){
        serverCtrl = this.gameObject.AddComponent<ServerRequestController>();
        uiCtrl =this.gameObject.AddComponent<UIController>();
        serverCtrl.GetData(uiCtrl.SetUI);
    }
}
public class UIController:MonoBehaviour{
    public void SetUI(Data data)
    {
         SetTopImage(data.topImage);
         SetBottomImage(data.bottomImage);

        // And so on
    }
}
public class ServerRequestController:MonoBehaviour{
    public void GetData(Action onCompletion){
        // This may be a coroutine if you fetch from server
        Data data = GetDataFromSomewhere();
        // At this point, your data is ready
        onCompletion(data);
    }
}

Thanks to this, you are now able to know exactly when a piece of code is ready.

Everts
  • 10,408
  • 2
  • 34
  • 45
  • Brilliant. Indeed I did use "onlevelwasloaded" but the UI element may not be there, ready to go, when I invoke it, which lead to errors. This take care of syncing, and it is really a nice way to deal with the problem. Thanks! –  Feb 29 '16 at 08:33
  • Could I implement this in my singleton game manager? That object is loaded when the main menu scene is loaded, so it persist when I load the new scene. –  Feb 29 '16 at 08:35
  • 1
    Singleton is not related to persistent object. This is actually two separate patterns. If you wish to make it persistent, you would use DontDestroyOnLoad. If you wish to make it a singleton, then you would make it inherit from a singleton class. Both are possible together since they are not related (they kinda complete each other in some ways). Just make sure you are not creating new instances when coming back to the scene that created your manager. Your singleton should take care of that but keep an eye on it though. – Everts Feb 29 '16 at 08:53
  • There is no such thing as a "singleton" in an ECS scene-based game engine such as Unity. Note that *every game object is in fact a singleton*. If you think you have a singleton you don't, and you don't understand OO/ECS. (Here's an angry essay on the topic! http://stackoverflow.com/a/35524924/294884 ) If you have a "game manager", which is fine, that is a "script" on a "game object". That's all there is to it. It's Just That Simple. – Fattie Feb 29 '16 at 13:28
  • @fafase old bean - is there a typo in the code? you'd have to do that in `Start` not `Awake` or else everything may not be `Awake` 'd, right? – Fattie Feb 29 '16 at 13:41
  • Mmmm no. it will do just fine. As long as the new component are not relying on data that would be set later on in the controller's awake. Awake is called as a ctor, so Awake in MyController triggers and create the server object, it then gets its own awake run, same for UIController. At that point they are both initialised. Their Start methods are not yet done. Then it gets back to the original awake that calls the GetData and so on. Or what did you mean? – Everts Feb 29 '16 at 14:21