Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How can I get an instance of a GameManager when I want to test a scene?

Discussion in 'Scripting' started by Bazz_boyy, Oct 18, 2016.

  1. Bazz_boyy

    Bazz_boyy

    Joined:
    May 22, 2013
    Posts:
    192
    Okay so I have a preload scene that has the GameManager obj in it. The problem I'm having, is that If I want to test a scene that requires the GameManager, unless I play through the game from the preload scene to that particular scene, I won't have a GameManager obj.

    Currently I just have a GameManager obj in every scene and I could just delete it later when I ship, but I feel like this is a hassle.

    Is there anything I can do to solve this?
     
  2. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    We just had a big discussion on this earlier today. Essentially, the easiest method to do Game Managers is to simply make a prefab from the Game Manager and use it in every scene as separate objects. Data persistence is the problem, and the only real way to solve that with using a prefab Game Manager object like this is by storing any data you want to be persistent in a static database that isn't attached to any GameObject.

    Now, for an alternative. First, you can set your Game Manager to DontDestroyOnLoad and keep it loaded throughout the life of the program. ...but there's a trade-off- you won't be able to reference the Game Manager by dragging and dropping it into the inspector anywhere in the program, because in Scenes 2+, it won't exist to reference yet without playing Scene 1 first (the problem you're describing). If you drag in the prefab and make a new copy for each scene, but have DontDestroyOnLoad set, you'll end up creating multiple copies in the cases where you actually do play from Scene 1, so this isn't really perfect.

    One common addition to this is to use what's called a singleton, which is the Game Manager component making a single static reference to itself, then any further copies that are made (from new scenes loading) will see that the static reference is already set, and destroy themselves to keep any duplicates from existing. What's important to keep in mind in these situations is that, even though you have the Game Manager existing in each scene now, those Game Manager copies will NOT exist in their current form when you play through from Scene 1, because the original will still exist and the duplicates (one of which you're using in the editor) will never get off the ground. That being the case, you still can't use direct object references in the inspector, because they'll be broken references later- but you can use the static reference from the singleton to access the object, so that's fine as long as you know to look out for it.

    So, you can make a Game Manager that doesn't destroy itself, and is easily referenced from anywhere (singleton components), but you're still going to get that penalty from having to spawn duplicates, and that's sort of annoying in the final build. One final tip is to set the Game Manager with the EditorOnly tag in the prefab, but go back to the first scene in the game and take that tag off. This will make it so that you can use the duplicated Game Manager objects in the various scenes for testing, but not waste resources re-creating them on each scene load just to turn around and immediately destroy them again, and it'll mean you don't have to cripple yourself by going through and deleting all of the extra managers just to turn around and have to recreate them for testing when a problem crops up.

    So, long story short- use a permanent Game Manager object and deal with all sorts of little annoying details in implementation, like not being to drag and drop references in the inspector, or use a prefab to recreate a bunch of scene-only Game Manager objects and keep the ability to drag and drop the reference wherever you like, but not carry data over to other scenes without the use of a separate static database of some kind.
     
    Last edited: Oct 18, 2016
  3. Kalladystine

    Kalladystine

    Joined:
    Jan 12, 2015
    Posts:
    227
    You skipped the additive scene method :) (and while it might be debatable in production, for testing it's really nice).

    Create a new scene, name it GameManagerTestScene or similar.
    Put 1 instance of your GameManager there, deleting everything else from the scene.
    Set the GM values however you want (don't apply to prefab). Save the scene.

    Whenever you need to add a GameManager to your scene - drag that scene to the hierarchy. It will load it additively.

    Pros:
    - you don't change anything in your scenes or GameManager code, so nothing to revert
    - you can right-click -> unload/load scene any time, if you want to f.e. see what breaks if it's not there (or if defaults work correctly etc)
    - you can change GM settings without worrying that it will affect your "real" GM (just break the prefab connection)
    - static accessors work normally (just like DontDestroyOnLoad)
    - it can be normally found with GameObject.Find*

    Cons:
    - you can't drag&drop it to reference fields (same as with DontDestroyOnLoad)


    Adding this just as an alternative, use whichever suits your use case the best.
     
    Kiwasi likes this.
  4. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Additive loading is a good method. I would go one step further and combine it with a Singleton.

    Set up a static property which returns the GameManager (Or for extra points an instance of IGameManager).

    Inside the property check first to see if a GameManager exists. If it does not, load a GameManager with additive scene loading.

    This method would work for production code too.
     
  5. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    Very cute ^_^

    In my particular case though, I never actually use the static singleton references to the manager components except for quick testing, so that won't guarantee that they're loaded. All of the big managers in my project (general manager, video manager, audio manager, etc...) are completely decoupled and just register/broadcast to generic events. I do use the additive scene method with the Game Manager, as suggested, but I have to manually add the manager scene to the current test scene, sadly.

    Woe is me? lol. I adore nothing having any actual knowledge of the managers though.
     
    Last edited: Oct 18, 2016