Issues with Save / Load system

Hello everyone,

We’ve had a number of perplexing issues with our save system, and after days of beating my head against the wall trying to figure out what exactly is going on, I finally decided to bite the bullet and bring it here. To start, we initially had another issue that is chronicled here:

Essentially, we had a performance issue that was being caused because instead of the autosave feature saving the game every 35 seconds, it was waiting 35 seconds from game start, and then saving continually. The issue was how we wrote the script:

function SaveGame()
{
	for(var x = 1; x>0; x++)
	{
		yield WaitForSeconds(35);
		PlayerPrefsX.SetIntArray("Ammount in inventory", inventoryScript.ammountInInventoryArray);
		PlayerPrefsX.SetVector3("PlayersPosition", gameObject.transform.position);
		PlayerPrefsX.SetVector3("PlayersRotation", gameObject.transform.eulerAngles);
		PlayerPrefs.SetInt("CurXp", Playerhealth.curXp);
		PlayerPrefs.SetInt("NextScene", GameObject.Find("Player 2").GetComponent(levelvar).LVL);
		PlayerPrefs.SetFloat("slider", GameObject.Find("TOD").GetComponent(TOD).slider);
	    PlayerPrefs.SetInt("MaxXp", Playerhealth.maxXp);
	    PlayerPrefs.SetInt("MaxHealth", Playerhealth.maxHealth);
	    PlayerPrefs.SetInt("CurHealth", Playerhealth.maxHealth);
	    PlayerPrefs.SetInt("Level", Playerhealth.level);
	    PlayerPrefs.SetInt("Money", Playermoney.curMoney);
	    PlayerPrefs.SetInt("Club", WeaponInv.Club);
        PlayerPrefs.SetInt("Sword", WeaponInv.Sword);
        PlayerPrefs.SetInt("Camera", WeaponInv.Camera);
        PlayerPrefs.SetInt("SoulReaver", WeaponInv.SoulReaver);
        PlayerPrefsX.SetBool("weaponready", Player3Weapons.weaponready);
        PlayerPrefsX.SetBool("swordready", Player3Weapons.swordready);
        PlayerPrefsX.SetBool("cameraready", Player3Weapons.cameraready);
        PlayerPrefsX.SetBool("obtainedWeapon02", Player3Weapons.obtainedWeapon02);
        PlayerPrefsX.SetBool("obtainedWeapon03", Player3Weapons.obtainedWeapon03);
        PlayerPrefsX.SetBool("obtainedWeapon04", Player3Weapons.obtainedWeapon04);
        PlayerPrefsX.SetBool("obtainedWeapon05",Player3Weapons.obtainedWeapon05);
        PlayerPrefsX.SetBool("IDied", GameObject.Find("Player 2").GetComponent(Playerhealth).iDied);
	}
}

function LoadGame()
{
	inventoryScript.ammountInInventoryArray = PlayerPrefsX.GetIntArray("Ammount in inventory");
	GameObject.Find("Player 2").GetComponent(levelvar).LVL = PlayerPrefs.GetInt("NextScene");
	gameObject.transform.position = PlayerPrefsX.GetVector3("PlayersPosition");
	gameObject.transform.eulerAngles = PlayerPrefsX.GetVector3("PlayersRotation");
	Playerhealth.curXp = PlayerPrefs.GetInt("CurXp");
    Playerhealth.maxXp = PlayerPrefs.GetInt("MaxXp");
    Playerhealth.maxHealth = PlayerPrefs.GetInt("MaxHealth");
    Playerhealth.curHealth = PlayerPrefs.GetInt("CurHealth");
    Playerhealth.level = PlayerPrefs.GetInt("Level");
    Playerhealth.iDied = PlayerPrefsX.GetBool("IDied");
    Playermoney.curMoney = PlayerPrefs.GetInt("Money");
    WeaponInv.Club = PlayerPrefs.GetInt("Club");
    WeaponInv.Sword = PlayerPrefs.GetInt("Sword");
    WeaponInv.Camera = PlayerPrefs.GetInt("Camera");
    WeaponInv.SoulReaver = PlayerPrefs.GetInt("SoulReaver");
    Player3Weapons.weaponready = PlayerPrefsX.GetBool("weaponready");
    Player3Weapons.swordready = PlayerPrefsX.GetBool("swordready");
    Player3Weapons.cameraready = PlayerPrefsX.GetBool("cameraready");
    Player3Weapons.obtainedWeapon02 = PlayerPrefsX.GetBool("obtainedWeapon02");
    Player3Weapons.obtainedWeapon03 = PlayerPrefsX.GetBool("obtainedWeapon03");
    Player3Weapons.obtainedWeapon04 = PlayerPrefsX.GetBool("obtainedWeapon04");
    Player3Weapons.obtainedWeapon05 = PlayerPrefsX.GetBool("obtainedWeapon05");
	inventoryScript.displayChanged = true;
	if( PlayerPrefs.GetFloat("slider") != 0)
	{
		GameObject.Find("TOD").GetComponent(TOD).slider = PlayerPrefs.GetFloat("slider");
	}
	
	loadGame = false;
}

That very nearly worked perfectly, other than the performance issue after several minutes of gameplay, when Garbage Collector got bogged down. So we fixed the issue by taking out the

for(var x = 1; x>0; x++)

Now, the game saves every 35 seconds like clockwork. Unfortunately, it’s screwed a bunch of other stuff up. The most glaring issue is player position. When the player switches certain scenes, their position is way off. The most obvious thought is that now that game saves every 35 seconds, that they might be pushed back to their position 35 seconds ago. Unfortunately, no fix we’ve tried to implement on the scene switch script works. We’ve attempted to save position right at that time, (ontriggerenter) with no success, and have attempted to move the player to a predetermined location before (and after) the switch, with no success. The Scene Switch script is below:

var nextScene : int;
var EnableText : GUIText;
var EnableText2 : GUIText;
var EnableText3 : GUIText;
var EnableText4 : GUIText;
var EnableText5 : GUIText;
var EnableText6 : GUIText;
var EnableText7 : GUIText;
var EnableText8 : GUIText;
var EnableText9 : GUIText;
var EnableText10 : GUIText;
var EnableText11 : GUIText;
var EnableText12 : GUIText;
var EnableText13 : GUIText;
var EnableText14 : GUIText;
var BibleText : GUIText;
var location : Vector3;

var LoadingScreen : GameObject;

function OnTriggerEnter (col : Collider) {
if(col.gameObject.tag == "Player") {
EnableText.enabled = true;
BibleText.active = true; 
BibleText.enabled = true;
EnableText.active = true;
EnableText2.enabled = false;
EnableText2.active = false; 
EnableText3.enabled = false;
EnableText3.active = false; 
EnableText4.enabled = false;
EnableText4.active = false; 
EnableText5.enabled = false;
EnableText5.active = false; 
EnableText6.enabled = false;
EnableText6.active = false; 
EnableText7.enabled = false;
EnableText7.active = false; 
EnableText8.enabled = false;
EnableText8.active = false; 
EnableText9.enabled = false;
EnableText9.active = false; 
EnableText10.enabled = false;
EnableText10.active = false; 
EnableText11.enabled = false;
EnableText11.active = false; 
EnableText12.enabled = false;
EnableText12.active = false; 
EnableText13.enabled = false;
EnableText13.active = false; 
EnableText14.enabled = false;
EnableText14.active = false; 
LoadingScreen.active = true; 
Debug.Log("Loaded level");
//col.gameObject.transform.position = Vector3(3619.196,1347.481,2598.744);
col.gameObject.GetComponent(levelvar).saveLvl(nextScene);
PlayerPrefsX.SetVector3("PlayersPosition", gameObject.transform.position);
PlayerPrefsX.SetVector3("PlayersRotation", gameObject.transform.eulerAngles);
Debug.Log("saved level");
Application.LoadLevel(nextScene);
col.gameObject.transform.localPosition = location;
}
}

It just seems like no matter what, the player ends up at a spot away from whatever coordinates I enter. We’ve even attempted commenting out the save / load calls in the save script for player position and just having them on the scene switch script, but that too was an utter failure. To make it clear, this is a role playing game where when one scene loads into another, the player is actually very near the same spot on the map. (well, should be) When the game was saving “wrong” the system worked fine, but now that the system is “working” they’re not loading in the proper place. I’m sorry if this question is all over the place. Have been extremely frustrated by it, and was hoping to not have to ask here and waste people’s time. Thanks for any help anyone is able to provide. God bless.

I hope its better to re- write your Data Save script in simple way. Create a single serializable class for your meta data and save that class in to a single PlayerPref. it will solve most of your problems.

[Serializable]
public class PlayerData 
{
	public int Score;	
}


public class HudController : MonoBehaviour 
{

	private PlayerData 	m_PlayerData;
	
	
	private void Awake()
	{
		Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");
		m_PlayerData = new PlayerData ();
	}
	
	public void SaveData()
	{
		try {
			
			//Get a binary formatter
			BinaryFormatter binaryFormatter = new BinaryFormatter();
			//Create an in memory stream
			MemoryStream memoryStram = new MemoryStream();
			//Save the scores
			binaryFormatter.Serialize(memoryStram, m_PlayerData);
			//Add it to player prefs
			PlayerPrefs.SetString("MetaData", 
			                      Convert.ToBase64String(
				memoryStram.GetBuffer()));
			//Debug.Log("Data Saved");
		} 
		catch (Exception ex) 
		{
			Debug.LogError("SaveDataException :"+ex.ToString());	
			
		}
	}

	private void LoadData()
	{
		string data = PlayerPrefs.GetString("MetaData", "null");
		//If not blank then load it
		if(!data.Equals("null"))
		{
			try 
			{
				//Binary formatter for loading back
				BinaryFormatter binaryFormatter = new BinaryFormatter();
				//Create a memory stream with the data
				MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(data));
				//Load back the scores
				m_PlayerData = (PlayerData)binaryFormatter.Deserialize(memoryStream);
				
				m_Label1Text = m_PlayerData.Score.ToString();
			} 
			catch (Exception ex) 
			{
				Debug.LogError("MetaData read error :"+ ex.ToString());
			}
		}
	}
}