How to keep certain information when reloading a level

I'm trying do decide which way would be better to reset a match and return everything to its normal positions so that they can be replayed from the default spots.

The options I came up with were: -Reset all the locations manually using code to save the locations to reset to.

or

-Reset all the locations by just recalling the "Application.LoadLevel("Scene")

I want to do this while keeping in mind that there are variables and game objects that I want to keep or destroy such as the score, the number of players and their names and other specifics.

the second option seems much easier, but the problem is deciding which game objects I want to save such that the variables I want to keep are preserved.

I have a individual player status, a level status, and the status of the targets which are being struck(which disappear when hit)

If I were to use the DoNotDestroyOnLoad(this) what are the specifics that are applied to it? does it only cover Game Objects or can I get more precise and pick and choose variables to save for the next round? if not whats a good set up that possible?

The DontDestroyOnLoad function is generally used to preserve an entire GameObject, including the components attached to it, and any child objects it has in the hierarchy.

You can't specify individual variables to preserve, but if you want to minimise the amount of data preserved, you could create an empty GameObject, and place only the script containing the variables you want preserved on it.

Then, when you place this line in your script's Awake() function,

DontDestroyOnLoad (this);

it will cause just this empty GameObject and the attached script to persist through the load.

That said, it's also relatively easy to have a script on each object which stores the original position and rotation values of each object, and has a "Reset" function which sets the current position and rotation back to the original values (and perhaps zeroes the velocity and angularVelocity values too).

It would look something like this:

var originalPosition : Vector3;
var originalRotation : Quaternion;

function Start() {
    originalPosition = transform.position;
    originalRotation = transform.rotation;
}

function Reset() {
    transform.position = originalPosition;
    transform.rotation = originalRotation;
}

This is a good question. I've been thinking about both it and another post talking about having a LevelManager object, which can manage data between level/scene changes. Plus the problem of how to make an object into a Singleton, so you don't get multiple copies.

Here is my attempt at solving the problem. First, I posted a package with all the code on the forums at: Simple Demo of a LevelManager.

I will admit, like a lot of people, I don't like Singletons... :( But you do need some way to prevent duplicate objects. My solution involves two C# scripts (s_bootstrap and s_LevelManager), and two GameObjects (Bootstrap and LevelManager, which is turned into a Prefab).

I create two empty Gameobjects, Bootstrap and LevelManager. On LevelManager, I attach the script s_LevelManager. Then I make LevelManager into a Prefab, and delete it from the Hierarchy. This way it won't be created automatically when the level starts, so no duplicates.

On Bootstrap, I attach the script s_bootstrap, and set a Prefab variable to the LevelManager Prefab object. Bootstrap should be on the first scene/level to load.

This is the sequence of events when execution starts: The first scene loads, creates a Bootstrap GameObject. Bootstrap check for a LevelManager object, and if none - creates one, makes it immortal with DontDestroyOnLoad(). Then Bootstrap suicides :) it does Destroy() on itself, removing it from the Hierarchy. So the next time the scene is loaded, Bootstrap will not be created. Leaving an un-attached LevelManager floating somewhere in cyberspace.

Then, any object that wanted to reference the LevelManager GameObject could find it by name, get a reference the s_LevelManager script, and could call the public functions on that script:

GameObject tmp = GameObject.Find("LevelManager");
if (tmp != null) {
    s_LevelManager slm = tmp.GetComponent<s_LevelManager>();
    String curLevel = Application.loadedLevelName;
    int count = slm.getTimes();
    msg.text = curLevel + ", changes = " + count;
    slm.bumpTimes();
}

I decided not to include the code for s_bootstrap/s_LevelManager, keep things from getting too long :) But again, if you do want the code, it's at: Simple Demo of a LevelManager.

You can also try to look into PlayerPrefs i will give you a link to unity api for you.

public float myFloat;

void RememberMe ()
{
    PlayerPrefs.SetFloat("MyValue",myFloat);
    PlayerPrefs.GetFloat("MyValue");
}

Well after applying what was said about DontDestroyOnLoad I came up with this.

It took me a while to figure it out but heres what I have so far.

// This object will presist and will delete itself if there was already a previous object preventing collisions
var dSetNumber : int = 0;
var dFramePoints : int = 0;
var dStrikeCount : int = 0;
var dTotalStrikes : int = 0;
var dIsStrike : boolean = false;
var dIsSpare : boolean = false;

var pins : PinStatus[];
var pChar : Status;
private var gameLink : LevelState;
private var dataManager : PlayerDataManager; // Not being used
function Awake()
{

   collisions = FindObjectsOfType (DataState);
   for (var collision : DataState in collisions)   //This method seems to work just fine I'm not sure why.
{

    if(transform.GetInstanceID() < collision.GetInstanceID())
        Destroy(gameObject); 
}

DontDestroyOnLoad(this);
//if((transform.name == "PlayerData " + GetInstanceID()) == GameObject.Find("PlayerData 10916"))
//  Destroy(gameObject);

gameLink = FindObjectOfType(LevelState);
if(!LevelState)
{
    Debug.Log("LevelState.js does not exist");
}

}
function GetLatestSet() : int
{

    return dSetNumber;      
}

function StoreGame()
{

        dSetNumber = gameLink.setNumber;
        dFramePoints = 10 - gameLink.numberOfPins;

}

function SavePlayer()
{
    //dStrikeCount = pChar.strikeCount;
    //dIsStrike = pChar.isStrike;
    //disSpare = pChar.isSpare;
    //dTotalStrikes = pChar.totalStrikes;

}

That solves the keeping the data part now I have to actually send the data back to the game when it gets reloaded. look good? EDIT This doesn't work too well either.

Hi,

I came up with this solution on a problem of RELOADIN SAME level and still wanted to retain data.

It is quite simple. You will have empty level (scene) with only one Game Object and script attached to it.
This will be our special level. Let’s call this level LEVEL0.

Make this object indestructible with DontDestroyOnLoad(), called from Awake() function.
Put all global variables in this script, with or without static prefix – your choice.
After DontDestroyOnLoad() - load LEVEL1, which is your game level or menu level.

Any time you want to reload LEVEL1, you can. All data will be there and since you are not loading LEVEL0, your GameObject will not multiply.

In this way you can make as much levels as you want.
Just make those levels after our special LEVEL0, and never load LEVEL0 again.

Regards.

When you use global variables you can save and modify the information of this global variable when you go to other scene and comeback to the initial scene. You know: You have your global variable in your initial scene, you modify this variable in this scene, you go to other scene with Application.LoadLevel and modify the value of this global variable and when you comeback to your initial scene with Application.LoadLevel you can watch how this modification is reflected on the value inside your initial scene.

I am having problems getting an empty object called myObject in the calling level to be passed to a called level. I have a script called myScript attached to another empty object in the called level with the following script:
function Awake(){
DontDestroyOnLoad(myObject);
}

The myObject from the calling level never appears in the called level. What am I missing?

Thanks…

DoNotDestroyOnLoad sucks big time. I don’t understand unity’s logic here. it’s supposed to keep the object and vars into the next scene, but all it really does is instantiates it, so why bother adding this feature when I can just simply instantiate it?

for the first time I’ve felt unity is a waste of money. I wish I had tested it first, at least now i know why unity isn’t used in big projects.

Yes you can use all the data storage methods but how tedious and counter intuitive that is, not to mention the time it would take to build a complex game.

Just because unity team didn’t do the right thing in this little area means that big projects will take years to finish.

You can create an object in first scene, attach a sript to it and sen value of variable in this script. For example if you want to send user login script attachet to game object that will survife after second scene load should be:

// User login:

public var userLogin : String;

function Awake() {

// Do not destroy this game object:

DontDestroyOnLoad(this);

}

Set userLogin in first scene and read in second.

Complete example can be found in my blog http://unity-tutorials.blogspot.com/. Listing 20 and 21.