0

I'm making a Balloon popping game, and I want to get a prize for some amount of score for example if you made a score of 10 you get a sticker or if you made a score of 20 you get a keyholder, and if you have score 0 you get a try again text so the problem is that when I finish the game it displays the try again text then when you open a different program (like going to a folder or anything outside of unity the text refresh and then I get the right text. I have tried using update, LateUpdate and FixedUpdate but nothing changes.

Here is the script:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.UI;
 using UnityEngine.SceneManagement;
 public class CountDownTimer : MonoBehaviour
 {
 //public string levelToLoad;
 public float timer = 60f;
 public Text timerSeconds;
 public GameObject panelWin, score, time, pausa;
 public int _playerScore;
 public Text premio;
 // Use this for initialization
 void Start ()
 {
 timerSeconds = GetComponent<Text>();
 time.SetActive(true);
 panelWin.SetActive(false);
 Time.timeScale = 1;
 }

 // Update is called once per frame
 void LateUpdate ()
 {
 timer -= Time.deltaTime;
 timerSeconds.text = timer.ToString("f0");
 if (timer <=0)
 {
     if (PlayerPrefs.HasKey("Points"))
     {
         _playerScore = PlayerPrefs.GetInt("Points");
         if (_playerScore == 0)
         {
             premio.text = "Intenta de nuevo!";
         }
         else
         {
             if (_playerScore >= 1 && _playerScore <= 10)
             {
                 premio.text = "Tu premio es: una calco Bebé a bordo";
             }
             else
             {
                 if (_playerScore >= 11 && _playerScore <= 20)
                 {
                     premio.text = "Tu premio es: un llavero Huggies";
                 }
                 else
                 {
                     if (_playerScore >= 21 && _playerScore <= 30)
                     {
                         premio.text = "Tu premio es: un pack de toallitas";
                     }
                     else
                     {
                         if (_playerScore >= 31 && _playerScore <= 40)
                         {
                             premio.text = "Tu premio es: un pack de 
pañales";
                         }
                         else
                         {
                             if (_playerScore >= 41 && _playerScore >= 50)
                             {
                                 premio.text = "Tu premio es: un bolso 
Huggies";
                             }
                         }
                     }
                 }

             }
         }


     }
     panelWin.SetActive(true);
     score.SetActive(false);
     //time.SetActive(false);
     pausa.SetActive(false);
     if (panelWin == true)
     {
         Time.timeScale = 0;
     }

 }
 }
 public void DoARestart()
 {
 SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
 }
 public void Menu()
 {
 SceneManager.LoadScene("TitleScreen");
 }
 }

This is the GameController Script:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class GameControllerScript : MonoBehaviour {

public Transform balloonPrefab;
public Text      scoreDisplay;
public Text scoreDisplayWin;

public int             _playerScore        = 0;
//private int             _multiplier         = 1;
private float           _timeSinceLastSpawn = 0.0f;
private float           _timeToSpawn        = 0.0f;
private List<Transform> _balloons;


private const int BALLOON_POOL = 30;

void Start () {
    PlayerPrefs.SetInt("Points", 0);
    _balloons = new List<Transform>();
    for (int i = 0; i < BALLOON_POOL; i++) {
        Transform balloon = Instantiate(balloonPrefab) as Transform;
        balloon.parent = this.transform;
        _balloons.Add(balloon);
    }
    SpawnBalloon();

    GameStart();
}

/*void InitMultiplier() {
    if (PlayerPrefs.HasKey("Multiplier")) {
        _multiplier = Mathf.Max (1, PlayerPrefs.GetInt ("Multiplier"));
    }
}*/

void InitPoints() {
    if (PlayerPrefs.HasKey("Points"))
    {
        _playerScore = PlayerPrefs.GetInt("Points");
    }
}

// Update is called once per frame
void Update () {
    _timeSinceLastSpawn += Time.deltaTime;

    if (_timeSinceLastSpawn >= _timeToSpawn)
    {
        SpawnBalloon();
    }

}

void SpawnBalloon() {
    _timeSinceLastSpawn = 0.0f;
    _timeToSpawn = Random.Range (0.0f, 2.0f);
    foreach (Transform b in _balloons) {
        BalloonScript bs = b.GetComponent<BalloonScript>();
        if (bs && !bs.isActive) {
            bs.Activate();
            break;
        }
    }
}

public void AddPoints(int points=1) {
    _playerScore += points;
    UpdateScoreDisplay();
}

public void GameOver() {
    SavePoints();
    SceneManager.LoadScene("TitleScreen");
}

void UpdateScoreDisplay() {
    scoreDisplay.text = "Puntaje: " + _playerScore.ToString();// + "(x" + 
_multiplier.ToString() + ")";
    scoreDisplayWin.text = "Tu puntaje es: " + _playerScore.ToString();
}

public void GameStart() {
    InitPoints();
    //InitMultiplier();
    UpdateScoreDisplay();
}

void OnApplicationPause() {
    SavePoints();
}

void OnApplicationQuit() {
    SavePoints();
}

void SavePoints() {
    PlayerPrefs.SetInt("Points", _playerScore);
}

}

I dont have any errors on the console, would be very glad if anyone can help! Thanks!

chino
  • 29
  • 6
  • @Programmer is not even the same subject, is not about saving or android so how is my question the same? – chino Oct 18 '17 at 14:59
  • *"How to refresh or update playerprefs"* Doesn't that mean saving/overriding existing data? – Programmer Oct 18 '17 at 15:11
  • no, I mean to refresh as get the last score. but I dont really know if that is the problem, or if im doing something wrong in the if statment, sorry for my english. – chino Oct 18 '17 at 15:14
  • @Programmer can you unmark as duplicate please, so other people can help – chino Oct 18 '17 at 15:18
  • Please change the title. "update playerprefs" means to save or write to old vales. Just reopened it – Programmer Oct 18 '17 at 15:19
  • 1
    Just a note: Playerprefs is strongly ***unrecommended*** for saving stuff like scores. It's real easy to cheat it (it's plain text). It's intended as a built-in way of saving **preferences** (settings, like BGM volume, control-schemes, preferred resolution, VSync flags, and so on...) Consider at least saving in binary format using `BinaryFormatter` instead. – CosmicGiant Oct 18 '17 at 15:39
  • Thanks @AlmightyR but the game wont be public. but that is not the problem here, so if can help with the real problem would be greate! – chino Oct 18 '17 at 15:47
  • As for the problem, it's probably where you're ***setting*** the `Points`. I strongly suspect a misaligned **execution order**, where the script responsible for updating the `Points` value is run ***after*** `CountDownTimer` is: **1)** This script makes the check for `_playerScore == 0` and results in `true` because `Points` hasn't been updated yet an is still a default `0` (thus printing `"Intenta de nuevo!"`). --- **2)** The script responsible for updating `Points` with the score is run (too late). --- **3)** Next frame, the check is run again (`LateUpdate`): Different `Points` => result. – CosmicGiant Oct 18 '17 at 15:54
  • Can you edit the question to include the code where `Points` gets updated/set? So that we can confirm this scenario? --- Also, add `Debug.Log("Points: "+_playerScore);` right after `_playerScore = PlayerPrefs.GetInt("Points");`... And something like `Debug.Log("Points at set: "+PlayerPrefs.GetInt("Points"));` right after you set `Points`, so we can check and confirm the order in which things are happening. --- If it prints the `"Points at set"` string ***before*** it prints `"Points:"`, then the problem is somewhere else. Otherwise, the problem is bad execution order. – CosmicGiant Oct 18 '17 at 16:07
  • Thanks @AlmightyR ! I will try that and also edit the question! – chino Oct 19 '17 at 11:30
  • Where is `GameOver()` called? – CosmicGiant Oct 19 '17 at 14:53

1 Answers1

0

Yep. You're not updating Points properly before it's used in CountDownTimer's LateUpdate()... Here is how your program flows:

  1. In the GameController script, you set Points to 0 at Start().
  2. In the CountDownTimer script, on every LateUpdate() (every frame), you check if playerPrefs.HasKey("Points"), which, from the first frame where GameController is enabled (runs Start()), which is probably the first game frame overall too, will result in true.
  3. Right after that, you set _playerScore to Points (0), and selects a value for premio.text based on that.
  4. Since...
    1. Your GameController.GameOver() is probably not called in the first frame of the script/game, in fact, probably not called for several frames.
    2. And since in the CountDownTimer.LateUpdate() (called every frame, including the first), from the first frame where GameControler.enabled == true (which is probably the first frame overall), Points will be there and equal 0.
  5. In CountDownTimer.LateUpdate(), you will get "Intenta de nuevo!" from the first frame where GameControler.enabled == true (which is probably the first frame overall), for several frames, until GameControler.GameOver() is called.
CosmicGiant
  • 6,275
  • 5
  • 43
  • 58