简体   繁体   中英

int variable resetting when loading another scene in unity

I created a football score calculator. I have a button that changes the scene, but when I change the scene and reopen it the score value is reset to 0. Here is the code:

public class Main : MonoBehaviour {
    public Text plusUp;
    public int value = 0;

    public void button(int sc)
    {
        SceneManager.LoadScene(sc);
    }

    public void plus()
    {
        value++;
        plusUp.text = value.ToString();
    }
}

1. You can use the method Object.DontDestroyOnLoad on the object that hold the variable you want to save. It will keep the GameObject this script is attached too alive when another scene is loaded:

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

See the documentation for more informations

You can also make a Singleton but this design pattern is a little more complex as Unity will destroy it when you load another scene. You still have to use DontDestroyOnLoad see how to implement this pattern on their GitHub page


2. Or you can save the value on the disk before loading another scene and then load the value with PlayerPrefs helpers methods:

public int value = 0;

void Awake()
{
    //Load the saved score (this value will be saved even if you restart the app)
    value = PlayerPrefs.GetInt("Score");
}

public void button1(int sc)
{
    //Save your value before you load the scene
    PlayerPrefs.SetInt("Score", value);
    SceneManager.LoadScene(sc);
}    

See the documentation for more informations on the types.

There's a few core concepts that would prove useful to understand this issue.

  1. Scope: Each scene operates in it's own scope. Any variables, objects, or changes that occur in one scene do not automatically transfer to another scene. When you start a scene, all objects in the scene are instantiated and initalized, and their Awake()/Start() methods are called if they are Monobehaviours.

  2. Initialization - When an object is instantiated, it is initialized with constructors or default values. Monobehaviours do not have constructors, so any variables will defer back to default values.

  3. Data persistence - When you change scenes, all game objects in the previous scene are destroyed, while all objects in the new scene are instantiated and initialized. Because all objects in the previous scene are destroyed, any values set on those objects disappear. You can prevent a GameObject from being destroyed with DoNotDestroyOnLoad(), but that does not overwrite the objects defined in the new scene. It is usually not advised to use DoNotDestroyOnLoad() as a core part of your game logic, as it often results in scenes being dependent on one another ("scene 1 has to define the values of a GameObject and pass it to scene 2 to be usable" = bad practice).

Solving your problem

It looks like you want score to persist as a value regardless of scene. Since all GameObjects and Monobehaviours are scoped within the scene, you can:

  1. Force the object to be scene-analagous using the Singleton pattern .

  2. Store score data to a file whenever it changes, and read from that file in the Start() method.

  3. My recommended approach: Use a ScriptableObject to hold the score, and refrence that object when changing the score and updating your gameObjects. ScriptableObjects are scoped at the project level, so they automatically persist between scenes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM