Search Unity

How to pass information from one Scene to another...

Discussion in 'Scripting' started by Sammual, May 19, 2009.

  1. Sammual

    Sammual

    Joined:
    Oct 28, 2008
    Posts:
    176
    Hey all,
    My non-work goal at work today is to find out how to pass information from one Scene to another. My research led me to the following ways;

    The way suggested by the documentaion
    Code (csharp):
    1.  
    2. // Make this game object and all its transform children
    3. // survive when loading a new scene.
    4. function Awake () {
    5. DontDestroyOnLoad (this);
    6. }
    7.  
    Code (csharp):
    1.  
    2. // user this in the new scene to find what you saved from the last scene
    3. var thatPersistingObject: GameObject;
    4. function Awake()
    5. {
    6.   thatPersistingObject = GameObject.Find("ObjectName");
    7. }
    8.  
    Problems seem to include textures and array data not being saved and having problems accessing anything from the game object.
    ------------------
    The easy way
    Code (csharp):
    1.  
    2. class CGlobals {
    3.     static public int money = 0;
    4.     static public bool paused = false;
    5.  
    6.     static void Startup(){
    7.         Debug.Log("Your stuff is my stuff and my stuff is my stuff");
    8.     }
    9. }
    10.  
    All you have to do is add the keyword static and the variable will persist from one scene to another? I think I am missing something.

    http://www.unifycommunity.com/wiki/index.php?title=AManagerClass seems to be mostly the same thing.
    ------------------

    Can anyone confirm the problems with DontDestroyOnLoad and/or explain the static / AManagerClass to me (Or is it just as simple as adding the keyword static)?

    Thanks,
    Sammual
     
  2. raiden

    raiden

    Joined:
    Feb 8, 2009
    Posts:
    333
    I use DontDestroyOnLoad and it works fine for me. The way I use it is I have a GameManager script that is loaded at the very beginning of the game, it handles everything from monitering the game progress and state, to activating and disabling game objects, hud stuff in the game, and updating/saving the game globals.

    I believe static variables are only good for active objects in the scene, so you would have to carry them over in order to use them.

    What I do is use DontDestroyOnLoad on everything I want to carry over, for example I build all my hud stuff in the start scene, and on those guiTexture objects, I add the DontDestroyOnLoad script, and all of those objects carry over to the game scene where they can be actived/deactivated or updated.

    Works really well for me.

    Hope that helps you out.

    -Raiden
     
    Bagheera likes this.
  3. Sammual

    Sammual

    Joined:
    Oct 28, 2008
    Posts:
    176
    That does help me out, thank you.

    Any chance I could get a small sample with the following?
    2 Scenes, one that sets up a game object and then a second that uses that object in some way.

    Sammual
     
  4. raiden

    raiden

    Joined:
    Feb 8, 2009
    Posts:
    333
    Hi Sammual, I would attach something, but I don't have any server space (thats on my list of todo's).

    I can tell you in code though basically how to get this started.

    The current project I am working on, my very first scene is designed to handle the opening logos, but I also have my most valuable object in that scene and its GameManager.

    This object has a script that holds references to everything in my game, including the main menu. The reason I did it this way is simply because I find it easier to reference one script throughout the game when I want to influence game decisions, such as "all my lives are gone", or "the user has decided to go back to the main menu", and many more things, those are just 2 examples.

    So here's a small take of GameManager , keep in mind, I program in javascript not c#:

    Code (csharp):
    1.  
    2. // Start.scene
    3. // Desc: Empty game object that has the 2 following scripts attached
    4. // GameManager.js
    5. //  DontDestroyObject.js
    6.  
    7. // GameManager.js
    8. // game setup values
    9. var menuMusic : AudioClip;
    10. var gameMusic : Audioclip;
    11. var maxScenes : int = 26;
    12. var highScore : int = 1000;
    13. var gameScore : int = 0;
    14. var gameLevel : int = 1;
    15.  
    16. // gui setup values
    17. var coverTexture : Texture2D;
    18. var logoTextures  : Texture2D;
    19. var menuTexture : Texture2D;
    20. var coverFade     : GameObject;
    21. var pauseGame     : GameObject;
    22. var life1         : GameObject;
    23. var life2         : GameObject;
    24. var life3         : GameObject;
    25. var levelText     : GameObject;
    26. var scoreText     : GameObject;
    27. var timerText     : GameObject;
    28. var gameWonText   : GameObject;
    29. var GWDelay  : float = 3.0; // Game Won text delay time
    30. var levelUpText : GameObject;
    31. var LUDelay  : float = 3.0; // Level Up text delay time
    32. var readyGameText : GameObject;
    33. var RGTDelay : float = 3.0; // Ready Game text delay time
    34. var gameOverText  : GameObject;
    35. var GODelay  : float = 3.0; // Game Over text delay
    36.  
    37. // game control values
    38. private var gameReady    : boolean = false; // should we show the "Ready" text
    39. private var gameWait     : boolean = true;  // run condition of all object loops, suspend them for other game states to process
    40. private var gameWon      : boolean = false; //diddo
    41. private var gamePause    : int = -1; // are we at a paused state (-1 is neither paused or unpaused, 0 is unpaused, 1 is paused)
    42. private var gameQuit     : boolean = false; // should we quit the game?
    43. private var gameMenu     : boolean = true;  // should we go back to menu?
    44. private var gameInst     : boolean = false; // should we go back to instructions?
    45. private var gameStats    : boolean = false; // should we display the game craft stats?
    46. private var gameRestart  : boolean = false; // should we restart the game
    47. private var levelCleared : boolean = false; // did we clear the level?
    48. private var displayStats  : boolean = false; // are we shoing the stats screen?
    49.  
    I'll stop here and explain some, I know that not all games will be like this, but you can see in my GameManger script, I am making references to alot of game objects, and variables. With the exception of a Texture and some control variables, all of these don't have anything to do with the Start scene, they are mainly used in the other game scenes, but again my reason for this is to have one place to control the game from, it just makes it easier to manage and keep up with how the game should flow.

    Now the neat part is adding the DontDestroyObject script which simply goes like:
    Code (csharp):
    1.  
    2. function Awake() {
    3.   DontDestroyOnLoad(this);
    4. }
    Easy enough, and now when I load my Menu.scene, my GameManager object will be accessible in that scene, and when I load my Game scene, my GameManager object is accessible from there too.

    So since my Start.scene holds all my menu/game hud stuff(textures, texts, etc.) I also to put the DontDestroyObject on those game objects and carry them over to the other scenes where I can access them to update them however I need to.

    Took me a while to get my head wrapped around it all, but once you understand how you can share objects between scenes like this, it really makes a difference in your programming, you can be really creative.

    Finally, one last note on GameManager, in any of my other game scripts, when I need to update say the "gameLevel" global that is defined in GameManager, in my other script, I start by getting a reference to GameManager:

    Code (csharp):
    1.  
    2. private var manager : GameManager;
    3.  
    4. function Start() {
    5.   manager = gameObject.FindObjectOfType(GameManager);
    6. }
    Now you have full control of GameManager in that script and can update values, change game control state booleans, whatever.

    For example, let's give an extra life, so we need to update gameLives in GameManager

    Code (csharp):
    1.  
    2. //... in your other game scenes function
    3. manager.GetComponent(GameManager).gameLives += 1;
    4. //....
    Then you can take it another step and update the GUIText that displays your lives(remember I built a GUIText object back in the Start scene, and applied DontDestroyObject to it).

    This part explains "static" on my GUIText, here is the code for it:
    Code (csharp):
    1.  
    2. static var levelText : GUIText;
    3.  
    4. function Awake() {
    5.     levelText = gameObject.GetComponent(GUIText);
    6. }
    7.  
    8. static function ShowLevel(level : int) {   
    9.     levelText.text = "Level : " + level.ToString();
    10. }
    Keep in mind a static function requires static variables, also remember you have to have in instance of this in order to call the function. So since this has a static variable and function, and.... you have access to it because even though this object was built in the Start.scene, but you added DontDestroyObject to it, which carried it over to the Game.scene, you have full control over it and once you have increased your "gameLevel" in GameManager, you can update your text level display in the game by simply calling:

    Code (csharp):
    1.  
    2. ... in your other game scenes function
    3. // you've updated your gameLevel, now update your display
    4. var newLevel = manager.GetComponent(GameManager).gameLives;
    5. GUITextLevel.ShowLevel(newLevel);
    6. // ....
    I hope that makes sense, as you can see your referencing GUITextLevel which is the script name of the GUIText object that shows your current level on the screen. Since it's all static, you don't have to access it through FindObjectOfType();

    Thats all there is to it! I'm no expert though, so if any other programmers would like to comment on my process, or inform me of better ways of doing what I'm doing, I'm always open for suggestions.

    Hope that helps you understand better.

    -Raiden
     
  5. Ender13

    Ender13

    Joined:
    May 3, 2009
    Posts:
    91
    Raiden, your explanation has helped me understand how to handle static/global variables and functions both in the same scene and across multiple scenes, so thank you very much!
     
  6. raiden

    raiden

    Joined:
    Feb 8, 2009
    Posts:
    333
    Thanks :) I'm glad I could help out.

    If anyone is interested, I've worked up a small example project that you can study if you need to. It's not an actual game, but it does show you how to pass objects from scene to scene, and makes use of static variables and functions.

    Just shoot me a PM with your email, and I'll send it to you.

    -Raiden
     
  7. Miboboio

    Miboboio

    Joined:
    May 20, 2009
    Posts:
    9
    may be you can use a singleton :

    Code (csharp):
    1.  
    2.  
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6.  
    7. public class GlobalVariable
    8. {
    9.     public string myGlobalVariable1, myGlobalVariable2;
    10.  
    11.    
    12.  
    13.     #region Init / Gestion du singleton
    14.  
    15.     private static GlobalVariable instance;
    16.     public static GlobalVariable Instance
    17.     {
    18.         get
    19.         {
    20.             if (instance == null)
    21.             {
    22.                 instance = new GlobalVariable();
    23.             }
    24.  
    25.             return instance;
    26.         }
    27.     }
    28.  
    29.     #endregion
    30.  
    31. }
    32.  

    and Call it :

    Code (csharp):
    1.  
    2.  
    3. GlobalVariable.Instance.myGlobalVariable1 = "toto";
    4. GlobalVariable.Instance.myGlobalVariable2 = "tutu";
    5.  
    6.  
    7.  
     
    ovirta likes this.
  8. Dinkyfish

    Dinkyfish

    Joined:
    Feb 20, 2009
    Posts:
    35
    Just found this topic and wanted to thank you, Raiden, for a very helpful post!

    Made so much sense that even I understood it :D
     
  9. DrHotbunz

    DrHotbunz

    Joined:
    Feb 14, 2009
    Posts:
    315
    I found it useful too. Thank you Raiden.
     
  10. rcalt2vt

    rcalt2vt

    Joined:
    Jun 6, 2009
    Posts:
    36
    Raiden, thank you!

    You explanation was amazing and helps a ton. Now to go back and rework my HUD structure...again. A great game can be ruined by a poor interface.

    - Ryan
     
  11. grfxman

    grfxman

    Joined:
    May 28, 2009
    Posts:
    309
    I just posted these very same questions. And of course I found this afterward :) Thanks this was a huge help !!
     
  12. schplurg

    schplurg

    Joined:
    Mar 21, 2009
    Posts:
    208
    How do you test a single scene in Unity if your Manager object is only loaded through the game start scene?

    In other words, I often test the level I'm working on without going through all the menus etc, so the Manager object would never load.

    I guess I need to change this practice at some point though (this is my first Unity game).

    Anyways just curious if anybody uses a workaround for that, or just always tests their game from a "normal launch". Of course, if your manager only holds certain variables you might still be able to test an individual scene without those.
     
  13. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    This where the Singleton plan comes in handy.
     
  14. schplurg

    schplurg

    Joined:
    Mar 21, 2009
    Posts:
    208
    I'm checking out the singleton scripts on the Wiki. I've set up a game manager object already, but as I stated, I'm afraid it my hamper my ability to test single levels at some point.

    I could just add some hotkeys that will allow me to jump to any level I want after I get to the main menu, but...I dunno.

    I'm trying to understand exactly what a singleton is, especially one that you don't attach to a component. I'm not an expert programmer (I'm using JS by the way). Can anyone explain fundamentally how a singleton works?
     
  15. raiden

    raiden

    Joined:
    Feb 8, 2009
    Posts:
    333
    I do this in JS by simply adding booleans for skipping parts of the scenes such as the menu scene, and also checks for skipping to different levels to test.

    All this is done in the GameManager.js script, and works well for me.

    -Raiden
     
  16. schplurg

    schplurg

    Joined:
    Mar 21, 2009
    Posts:
    208
    Cool, thanks. Ya, this seems to be working for me too. Thank you.
     
  17. AmineMessa

    AmineMessa

    Joined:
    Jan 6, 2017
    Posts:
    6
    Well , right before i read this , i got an idea (still implementing it)

    The idea is to use PlayerPrefs , and store an int ( 1 for true , 0 for false ) then call it from your other scenes right in Start() or Awake()

    i will use this for activating music on all my scenes , while the button to switch it on and off is in the menu

    Hope this is helpful ^_^
     
  18. HanSoloYolo

    HanSoloYolo

    Joined:
    May 22, 2017
    Posts:
    19
    If you are attempting to create a SceneManager Object with a SceneManager Script attached and this SceneManager Object is DontDestroyOnLoad, I suggest creating a New Empty Object with a New Script that will act as a ClickHandler.

    The Click Handler will be in each Scene and is what you will attach to your Button. In the ClickHandler script you will want to create a field for the SceneManager, then in the Start() get/set the SceneManager instance. I named my SceneManager LevelManager instead and this is the code I used and attached to my ClickHandler which I attached to my button in the scene.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class ClickHandler : MonoBehaviour
    4. {
    5.     private LevelManager levelManager;
    6.  
    7.     void Start ()
    8.     {
    9.         levelManager = LevelManager.instance;
    10.     }
    11.  
    12. #region ButtonCalls
    13.  
    14.     public void StartGame()
    15.     {
    16.         levelManager.StartSavedGame();
    17.     }
    18.  
    19.     public void GoToNextLevel ()
    20.     {
    21.         levelManager.StartNextLevel();
    22.     }
    23.  
    24.     public void RetryLevel()
    25.     {
    26.         levelManager.RetryLevel();
    27.     }
    28.  
    29. #endregion
    30. }
    I also have a LevelManager empty object in each scene and it is DontDestroyOnLoad. This is the block of code inside the LevelManager Script attached to the LevelManager Object for DontDestroyOnLoad.

    Code (CSharp):
    1. void Awake()
    2.     {
    3.         if (instance != null)
    4.         {
    5.             Destroy(gameObject);
    6.         }
    7.         else
    8.         {
    9.             instance = this;
    10.             GameObject.DontDestroyOnLoad(gameObject);
    11.         }
    12.     }
     
    Last edited: Aug 18, 2017
  19. shaji

    shaji

    Joined:
    Nov 3, 2018
    Posts:
    2
    Who knows better than this, eveyone knows things is trying to confuse people....suuuuuper.....