- Home /
Save/Load - Strange behaviour
I have written a basic save/load system, and it works just fine, except whenever I restart the game, the player's level increases by one. Every other property is loaded just fine. I don't have any explanation for this...
This is my code:
import System.IO;
static function save(slotNmbr) {
var sPath : String = Application.persistentDataPath + "/savegame" + slotNmbr + ".txt";
var sData : StreamWriter = new StreamWriter(sPath);
sData.WriteLine(Application.loadedLevel);
sData.WriteLine(PlayerStatus.level);
sData.WriteLine(PlayerStatus.exp);
sData.WriteLine(PlayerStatus.plHealth);
sData.WriteLine(PlayerStatus.lives);
sData.WriteLine(PlayerStatus.maxRange);
sData.WriteLine(PlayerStatus.maxMelee);
sData.WriteLine(PlayerStatus.pick[0]);
sData.WriteLine(PlayerStatus.pick[1]);
sData.WriteLine(PlayerStatus.pick[2]);
sData.WriteLine(PlayerStatus.pick[3]);
sData.Flush();
sData.Close();
PlayerPrefs.SetInt("Slot" + slotNmbr, 1);
}
static function load(slotNmbr) {
var lPath : String = Application.persistentDataPath + "/savegame" + slotNmbr + ".txt";
var lData : StreamReader = new StreamReader(lPath);
var stage = parseInt(lData.ReadLine());
var level = parseInt(lData.ReadLine());
var exp = parseInt(lData.ReadLine());
var plHealth = parseInt(lData.ReadLine());
var lives = parseInt(lData.ReadLine());
var maxRange = parseInt(lData.ReadLine());
var maxMelee = parseInt(lData.ReadLine());
var shields = parseInt(lData.ReadLine());
var mines = parseInt(lData.ReadLine());
var bombs = parseInt(lData.ReadLine());
var turbo = parseInt(lData.ReadLine());
lData.Close();
print(level);
GameObject.FindWithTag("Player").SendMessage("freeWP");
PlayerStatus.level = level;
PlayerStatus.expToLevel = PlayerStatus.expToLevelArr[PlayerStatus.level - 1];
PlayerStatus.exp = exp;
PlayerStatus.plHealthMax = 10 * PlayerStatus.multArr[PlayerStatus.level-1];
PlayerStatus.plHealth = plHealth;
PlayerStatus.lives = lives;
PlayerStatus.maxRange = maxRange;
PlayerStatus.maxMelee = maxMelee;
PlayerStatus.pick[0] = shields;
PlayerStatus.pick[1] = mines;
PlayerStatus.pick[2] = bombs;
PlayerStatus.pick[3] = turbo;
Application.LoadLevel(stage);
}
When I load a savegame from within the game, everything works as it should.
I have a Splash Screen Scene that automatically loads a 'hub' level. This in turn checks, if there is an autosave present and if so loads that, if not loads the first level. This hub scene has all important objects that are not destroyed on load (Player, Camera, Main Menu and the AutoLoader). When I delete the key for the autosave, the first level is loaded just fine. When I then close the game and restart (or restart it in the editor), the same level is loaded (since now there is an autosave there), but suddenly the player is at level 2. The print(level); line prints 1 to the console. When I repeat this, the pplayer is level 3, and the game prints 2.
The really strange thing is that values derived from the level (like max health and a damage multiplier) are calculated to level 2 although this should only happen an levelup, so it seems that the player somehow levels up, but that doesn't make sense...just to be sure, here is the PlayerStatus script:
//FX
var lvlUp : Transform;
//weapons
var weapons : Transform[] = new Transform[6];
static var maxRange : int = 0;
static var maxMelee : int = 3;
//health
static var lives: int = 3;
static var plHealth : int = 10; //player health
static var plHealthMax : int = 10; //maximum health
//power-ups
static var maxPowerUp : int = 5; //max number per power up
static var pick : int[] = [5,5,5,5]; //availible powerups - shield, mines, bombs, turbo
//EXP
static var level : int = 1;
static var maxLevel : int = 10;
static var multiplier : float = 1.0;
static var multArr : float[] = new float[10];
static var exp : int = 0;
static var expToLevel : int = 1000;
static var expToLevelArr : int[] = new int[10];
//weapons
static var i : int = 0;
static var j : int = 3;
function Awake() {
multArr = [1.0, 1.1, 1.3, 1.6, 2.0, 2.5, 3.0, 3.5, 4.0, 5.0];
expToLevelArr = [1000, 1500, 2500, 4000, 6000, 8000, 10000, 15000, 20000, 25000];
switch(i) {
case 0 :
gameObject.Find("Blaster").renderer.enabled = true;
gameObject.Find("Laser").renderer.enabled = false;
gameObject.Find("Plasma").renderer.enabled = false;
break;
case 1 :
gameObject.Find("Blaster").renderer.enabled = false;
gameObject.Find("Laser").renderer.enabled = true;
gameObject.Find("Plasma").renderer.enabled = false;
break;
case 2 :
gameObject.Find("Blaster").renderer.enabled = false;
gameObject.Find("Laser").renderer.enabled = false;
gameObject.Find("Plasma").renderer.enabled = true;
break;
}
GameObject.FindGameObjectWithTag("Player").GetComponent(Player).primAtt = weapons[i];
switch(j) {
case 3 :
gameObject.Find("Blade").renderer.enabled = true;
gameObject.Find("Mace").renderer.enabled = false;
gameObject.Find("Lance").renderer.enabled = false;
break;
case 4 :
gameObject.Find("Blade").renderer.enabled = false;
gameObject.Find("Mace").renderer.enabled = true;
gameObject.Find("Lance").renderer.enabled = false;
break;
case 5 :
gameObject.Find("Blade").renderer.enabled = false;
gameObject.Find("Mace").renderer.enabled = false;
gameObject.Find("Lance").renderer.enabled = true;
break;
}
GameObject.FindGameObjectWithTag("Player").GetComponent(Player).secAtt = weapons[j];
}
function Update() {
if(exp >= expToLevel) {
if(level <= maxLevel){
Instantiate(lvlUp, transform.position, Quaternion.identity);
level++;
exp -= expToLevel;
multiplier = multArr[level - 1];
expToLevel = expToLevelArr[level - 1];
plHealthMax = 10 * multArr[level-1];
plHealth = plHealthMax;
transform.GetComponent("Player").marker.gameObject.renderer.material.SetFloat("_Cutoff", 1 - (parseFloat(PlayerStatus.plHealth) / parseFloat(PlayerStatus.plHealthMax)));
}
}
if(statics.playerActive) {
if(Input.GetKeyDown(KeyCode.R)) {
i++;
if(i > maxRange)
i = 0;
switch(i) {
case 0 :
gameObject.Find("Blaster").renderer.enabled = true;
gameObject.Find("Laser").renderer.enabled = false;
gameObject.Find("Plasma").renderer.enabled = false;
break;
case 1 :
gameObject.Find("Blaster").renderer.enabled = false;
gameObject.Find("Laser").renderer.enabled = true;
gameObject.Find("Plasma").renderer.enabled = false;
break;
case 2 :
gameObject.Find("Blaster").renderer.enabled = false;
gameObject.Find("Laser").renderer.enabled = false;
gameObject.Find("Plasma").renderer.enabled = true;
break;
}
GameObject.FindGameObjectWithTag("Player").GetComponent(Player).primAtt = weapons[i];
}
if(Input.GetKeyDown(KeyCode.F)) {
j++;
if(j > maxMelee)
j = 3;
switch(j) {
case 3 :
gameObject.Find("Blade").renderer.enabled = true;
gameObject.Find("Mace").renderer.enabled = false;
gameObject.Find("Lance").renderer.enabled = false;
break;
case 4 :
gameObject.Find("Blade").renderer.enabled = false;
gameObject.Find("Mace").renderer.enabled = true;
gameObject.Find("Lance").renderer.enabled = false;
break;
case 5 :
gameObject.Find("Blade").renderer.enabled = false;
gameObject.Find("Mace").renderer.enabled = false;
gameObject.Find("Lance").renderer.enabled = true;
break;
}
GameObject.FindGameObjectWithTag("Player").GetComponent(Player).secAtt = weapons[j];
}
}
}
And my AutoLoader:
function Awake() {
Resources.UnloadUnusedAssets ();
if(PlayerPrefs.HasKey("Slot0"))
SaveLoad.load(0);
else
Application.LoadLevel ("test2");
}
PlayerStatus.expToLevel = PlayerStatus.expToLevelArr[PlayerStatus.level - 1]
Why -1? I would think that would get the exp needed to level "up" to be the exp needed for the previous level, and since the player will have more exp than that, he will dutifully level up in your update.
The array starts at 0, the level starts at one. At level one I want to access the first entry in the array and that is expToLevelArr[0].
In any case, it happens at 0 exp already.
Could you please post the whole script the level up script is in. I have an idea what might be happening, but I have to see the whole script.
I edited the post to include the complete PlayerStatus script.
The only time anything in that script is edited by other scripts (aside from load()) is when enemies die. They increase the exp by their exp-worth.
You are setting the expToLevel value in the Awake() function of the AutoLoader script, which may proceed the Awake() function of the PlayerStatus script which populates the array.
Answer by raoz · Apr 21, 2012 at 08:31 PM
The autoload awake might be called before the PlayerStatus Awake, thus rendering the Playerload obsolete. The reason why it doesn't give you an exeptcion is that you are initializing the exptolevel array when you are defining it and it gets initialized in constructor. Thus, if you change your PlayerStatus Update to this:
function Update() {
if(expToLevel == 0)
{
expToLevel = expToLevelArr[level - 1];
}
else if(exp >= expToLevel) {
if(level <= maxLevel){
Instantiate(lvlUp, transform.position, Quaternion.identity);
level++;
exp -= expToLevel;
multiplier = multArr[level - 1];
expToLevel = expToLevelArr[level - 1];
plHealthMax = 10 * multArr[level-1];
plHealth = plHealthMax;
transform.GetComponent("Player").marker.gameObject.renderer.material.SetFloat("_Cutoff", 1 - (parseFloat(PlayerStatus.plHealth) / parseFloat(PlayerStatus.plHealthMax)));
}
}
Then it should work.
Holy shit...never would have thought of that...thanks man. Works just perfectly.
Your answer
Follow this Question
Related Questions
Trying to save/load game, codes doesnt do anything. not even an error. 1 Answer
Saving lots of objects (Only answer in JavaScript) 1 Answer
simple checkpoint/save/load system in javascript 4 Answers
Not loading an object if it have be retained from a previous scene. 1 Answer
Simple save/load scripting for multi level iOS game. 1 Answer