Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass data (and references) between scenes in Unity

Tags:

c#

unity3d

How can I pass score value from one scene to another?

I've tried the following:

Scene one:

void Start () {     score = 0;     updateScoreView ();     StartCoroutine (DelayLoadlevel(20)); }  public void updateScoreView(){     score_text.text = "The Score: "+ score; }  public void AddNewScore(int NewscoreValue){     score = score + NewscoreValue;     updateScoreView (); }  IEnumerator DelayLoadlevel(float seconds){             yield return new WaitForSeconds(10);     secondsLeft = seconds;     loadingStart = true;     do {                 yield return new WaitForSeconds(1);     } while(--secondsLeft >0);      // here I should store my last score before move to level two     PlayerPrefs.SetInt ("player_score", score);     Application.LoadLevel (2); } 

Scene two:

public Text score_text; private int old_score;  // Use this for initialization void Start () {         old_score = PlayerPrefs.GetInt ("player_score");     score_text.text = "new score" + old_score.ToString ();       } 

but nothing displayed on screen, and there's no error.

Is this the correct way to pass data ?

I am using Unity 5 free edition, develop game for Gear VR (meaning the game will run in android devices).

Any suggestion?

like image 506
Mina Fawzy Avatar asked Aug 31 '15 08:08

Mina Fawzy


1 Answers

There are many ways to do this but the solution to this depends on the type of data you want to pass between scenes. Components/Scripts and GameObjects are destroyed when new scene is loaded and even when marked as static.

In this answer you can find

    1. Use the static keyword
    1. Use DontDestroyOnLoad
    1. Store the data local
    • 3a PlayerPrefs
    • 3b serialize to XML/JSON/Binary and use FileIO

1. Use the static keyword.

Use this method if the variable to pass to the next scene is not a component, does not inherit from MonoBehaviour and is not a GameObject then make the variable to be static.

Built-in primitive data types such as int, bool, string, float, double. All those variables can be made a static variable.

Example of built-in primitive data types that can be marked as static:

static int counter = 0; static bool enableAudio = 0; static float timer = 100; 

These should work without problems.


Example of Objects that can be marked as static:

public class MyTestScriptNoMonoBehaviour {  } 

then

static MyTestScriptNoMonoBehaviour testScriptNoMono;  void Start() {     testScriptNoMono = new MyTestScriptNoMonoBehaviour(); } 

Notice that the class does not inherit from MonoBehaviour. This should work.


Example of Objects that cannot be marked as static:

Anything that inherits from Object, Component or GameObject will not work.

1A.Anything that inherits from MonoBehaviour

public class MyTestScript : MonoBehaviour  {  } 

then

static MyTestScript testScript;  void Start() {     testScript = gameObject.AddComponent<MyTestScript>(); }  

This will not work because it inherits from MonoBehaviour.

1B.All GameObject:

static GameObject obj;  void Start() {     obj = new GameObject("My Object"); }   

This will not work either because it is a GameObject and GameObject inherit from an Object.

Unity will always destroy its Object even if they are declared with the static keyword.

See #2 for a workaround.


2.Use the DontDestroyOnLoad function.

You only need to use this if the data to keep or pass to the next scene inherits from Object, Component or is a GameObject. This solves the problem described in 1A and 1B.

You can use it to make this GameObject not to destroy when scene unloads:

void Awake()  {     DontDestroyOnLoad(transform.gameObject); } 

You can even use it with the static keyword solve problem from 1A and 1B:

public class MyTestScript : MonoBehaviour  {  } 

then

static MyTestScript testScript;  void Awake()  {     DontDestroyOnLoad(transform.gameObject); }  void Start() {     testScript = gameObject.AddComponent<MyTestScript>(); }  

The testScript variable will now be preserved when new scene loads.

3.Save to local storage then load during next scene.

This method should be used when this is a game data that must be preserved when the game is closed and reopened. Example of this is the player high-score, the game settings such as music volume, objects locations, joystick profile data and so on.

Thare are two ways to save this:

3A.Use the PlayerPrefs API.

Use if you have just few variables to save. Let's say player score:

int playerScore = 80; 

And we want to save playerScore:

Save the score in the OnDisable function

void OnDisable() {     PlayerPrefs.SetInt("score", playerScore); } 

Load it in the OnEnable function

void OnEnable() {     playerScore  =  PlayerPrefs.GetInt("score"); } 

3B.Serialize the data to json, xml or binaray form then save using one of the C# file API such as File.WriteAllBytes and File.ReadAllBytes to save and load files.

Use this method if there are many variables to save.

General, you need to create a class that does not inherit from MonoBehaviour. This class you should use to hold your game data so that in can be easily serialized or de-serialized.

Example of data to save:

[Serializable] public class PlayerInfo {     public List<int> ID = new List<int>();     public List<int> Amounts = new List<int>();     public int life = 0;     public float highScore = 0; } 

Grab the DataSaver class which is a wrapper over File.WriteAllBytes and File.ReadAllBytes that makes saving data easier from this post.

Create new instance:

PlayerInfo saveData = new PlayerInfo(); saveData.life = 99; saveData.highScore = 40; 

Save data from PlayerInfo to a file named "players":

DataSaver.saveData(saveData, "players"); 

Load data from a file named "players":

PlayerInfo loadedData = DataSaver.loadData<PlayerInfo>("players"); 
like image 194
Programmer Avatar answered Sep 22 '22 10:09

Programmer