Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How to get access of data from another scene?

Discussion in 'Getting Started' started by luyao795, Apr 12, 2016.

  1. luyao795

    luyao795

    Joined:
    Mar 17, 2016
    Posts:
    33
    So far for my game there are 2 scenes, one for main menu and one for main game. There is an input field in my main menu scene where players can enter a number. I want to use this number in another scene. How am I supposed to do this? I searched online for solutions and it seems that I need to use DontDestroyOnLoad, but after using that I got an error saying "NullReferenceException: Object reference not set to an instance of an object". I have no idea where went wrong.

    This is the script containing value of input field that I want to use in Scene2:
    Code (CSharp):
    1. public class ContentChange : MonoBehaviour {
    2.  
    3.     //public static ContentChange Instance;
    4.  
    5.     public Text startText;
    6.  
    7.     public Text quitText;
    8.  
    9.     public static Text difficulty;
    10.  
    11.     void Awake()
    12.     {
    13.         /*
    14.         if (Instance == null) {
    15.             DontDestroyOnLoad (gameObject);
    16.             Instance = this;
    17.         } else if (Instance != this)
    18.             Destroy (gameObject);
    19.             */
    20.         DontDestroyOnLoad (gameObject);
    21.     }
    And here is how I attempted to have access to that value in a script in Scene2:
    Code (CSharp):
    1. public string difficultyText;
    2.  
    3. void Awake()
    4.     {
    5.         difficultyText = ContentChange.difficulty.text;
    6.     }
    I also saw some people saying about using PlayerPrefs but someone pointed out that it's a bad habit to use PlayerPrefs.

    So if I want to use DontDestroyOnLoad, how should I adjust my code to make it work?

    Also I realized that after changing difficultyText to static, I was not able to reference the text in the inspector. Is this why the problem occurs? If so, then how could I link this Text in script to the one in Hierarchy?
     
    smock_74 and midhapulkit28 like this.
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    All right, first, ignore whoever said it's a bad habit to use PlayerPrefs. There's absolutely nothing wrong with it unless you have some special needs it doesn't serve (and you'll know when that's the case). It's simple and it works.

    However, even that isn't simple enough for this need. DontDestroyOnLoad is simpler, though I see it's caused a bit of confusion in this case. Static variables are simplest yet, and for a beginner, they are what I recommend.

    So: for the moment, forget PlayerPrefs. Forget DontDestroyOnLoad. All you need is a static variable that holds your actual data. And this must be plain old data: string, int, float, Vector3, etc. It must not be a Unity object, because Unity objects are destroyed when the next scene is loaded.

    So! You're already using a static variable here (difficulty). The problem is that it's of type Text. That's no good, because that Text object gets destroyed, and then you get a NullReferenceException when you try to do something with it in the next scene.

    Instead, you should declare difficulty as string. Now, you have a global string variable that lives forever, as long as your game is running. You can stuff data into it in one scene, and pull it out later in the same scene or a different scene — nothing can happen to it, until the game actually quits.

    Your next question might be: "great, but how do I get data from my Input field into this static variable?" Going through the UI tutorials might teach you enough to do that yourself, but if not, post back and we'll help.
     
    smock_74 and sparkwd like this.
  3. luyao795

    luyao795

    Joined:
    Mar 17, 2016
    Posts:
    33
    First, thanks for your explanation!

    And yes, now my question is "How do I get data from my Input field into this static variable?" I have some concerns in terms of this question.

    First one, does the location of the script where access to data from input field matter? Should the script attached to the input field or it can be attached to an empty game object?

    Second, when I was trying to get access to data in input field, what I did was:
    Code (CSharp):
    1. difficulty = GameObject.Find ("InputField").GetComponent<Text> ().text;
    I thought it would work, but it didn't. There was still NullReferenceException there.

    Third, say that the above code was correct, I'm still not sure where I should put this line into. I don't think it should be put in Awake or Start since if the user types in 3 then changes the mind and replaces it with 5, the actual value should be 5. It seems that Update is the right place, but somehow I just feel it's not that right. Maybe it's not a good thing to update the data every single frame. Instead, maybe just update it when the input value changes. But how to do that? I have no idea.

    Ahhh, so confused...
     
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    You're not too far off.

    First, it's important to understand that a static variable is not associated with any instance of the class. So as far as that variable is concerned, it doesn't have to be attached to any GameObject at all. It's really just a global variable, except that to access it, you have to prefix it with the name of the class (except for code that happens to be in the same class).

    Second: your line of code above would be fine if it were in the first scene, when InputField still exists, and assuming that that's what it is actually called. But there's still the (third) problem of where to put it. You're right, Awake and Start are not right because the user hasn't had a chance to type anything at that point (remember, this must happen in the first scene!), and doing it in Update is serious overkill.

    So, what you want to do is run some code that updates difficulty when the text actually changes. To do that, you hook up an event. If you don't know what an event is, then I believe you haven't done the UI tutorials! So quit wasting your time and go do them.

    Assuming you've done them, then you should have the basic idea. Just create a script that looks like this:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class ContentChange : MonoBehaviour {
    4.     public static string difficulty;
    5.  
    6.     public void DifficultyChanged(string value) {
    7.         Debug.Log("Aha, I see you've changed the value to: " + value);
    8.         difficulty = value;
    9.     }
    10. }
    ...and attach this to something in the first scene — I would recommend attaching it to the InputField object itself. Then, hook up the On Change event to invoke your DifficultyChanged method, passing in the new text.

    Now run, and you should see Debug.Logs whenever you change the value. And it's also storing this value in ContentChange.difficulty, which you can access (as simply ContentChange.difficulty) from the next scene.
     
    Tset_Tsyung likes this.
  5. luyao795

    luyao795

    Joined:
    Mar 17, 2016
    Posts:
    33
    Ahh, thanks for those valuable explanations! Now my game is really fully functional!
    Well, not really. My game still froze sometimes when there are actually places to put pieces (apparently it's still the Othello game). In other words, sometimes even if the AI has available moves, it doesn't do it. I need to debug on that as well. But finally I finished UI related stuff! Thanks again!
     
    Tset_Tsyung likes this.
  6. Deleted User

    Deleted User

    Guest

    Chiming in with my 2p

    From what I have read, PlayerPrefs is intended for exactly what it suggests: player preferences and system settings.

    As Joe suggests, for our purposes we can use it to save simple data for small games and projects that don't justify the effort of learning more complicated file IO techniques.

    However, if someone does decide it's time to learn more involved methods of file IO in Unity, a good place to start would be using XML files. Their big disadvantage is that players cane easily modify them, but otherwise seem to be the most robust and accessible method of saving data in Unity.

    More professional games use custom binary files, which I assume to be more challenging to set up than editable XML files.
     
  7. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,943
    At the same time this can be a big advantage. Some games are highly successful in part due to modding support.