0
\$\begingroup\$

I'm trying to create a reward system in my game where once the player dies, they have the option of watching a rewarded video ad after which the game restarts and the player score is set to score before the player died. I have been trying to figure this out for the last 2 hours but unable to achieve the desired result. This is my game manager script:

public class GameManager : MonoBehaviour
{
  public Player player;
  public Transform startLocation;

  public GameObject startPanel, ingamePanel, gameoverPanel; 

  private bool gameHasStarted;

  public enum GameStates
  {
    Start,
    InGame,
    GameOver
  }

  public float playerScore = 0;
  private int savedScore;
  private int difficultyLevel = 1;
  private int maxDiffLevel = 10;
  private int scoreToNextLevel = 10;    

  private void Start()
  {
    SetupNewGame();
  }

  void Update()
  {
    if(playerScore >= scoreToNextLevel)
    {
        LevelUp();
    }

    if (player.dead == false && gameHasStarted)
    {
        playerScore += Time.deltaTime * difficultyLevel;           
    }       
        
    if (playerScore > PlayerPrefs.GetInt("HighScore", 0))
    {
        PlayerPrefs.SetInt("HighScore", (int)playerScore);
    }       
}

 void LevelUp()
 {
    if (difficultyLevel == maxDiffLevel)
        return;
    scoreToNextLevel *= 2;
    difficultyLevel++;

 }

public void SetupNewGame()
 {       
    playerScore = 0;        
    player.transform.position = startLocation.position;              
    UpdateUI(GameStates.Start);
 }

 public void StartNewGame()
 {
    player.dead = false;
    gameHasStarted = true;
    UpdateUI(GameStates.InGame);
 }

public void GameOver()
{
    player.dead = true;
    gameHasStarted = false;        
    UpdateUI(GameStates.GameOver);        
}

void UpdateUI(GameStates gameState)
{
    startPanel.SetActive(false);
    ingamePanel.SetActive(false);
    gameoverPanel.SetActive(false);

    if (gameState == GameStates.Start)
    {
        startPanel.SetActive(true);
    }
    if (gameState == GameStates.InGame)
    {
        ingamePanel.SetActive(true);
    }
    if (gameState == GameStates.GameOver)
    {
        gameoverPanel.SetActive(true);
    }
}


 public void ReceiveLife()
 {        
    savedScore = (int)playerScore;        
    SceneManager.LoadScene(1);        
    playerScore = savedScore;       

 }
}

I have created a button for and added the ReceiveReward() in the onClick function. However when I click on this button, the score is reset to 0 and not the score before the player died. Can someone please help?

EDIT 1

I have added this code to the game manager:

private void Awake()
{
    if (instance == null)
    {
        instance = this;
    }
}

The score is still reverting to 0.

EDIT 2

As per the code provided by @DMGregory, the revive button is working on. Now I'm trying to implement reward based video ads in my game for two buttons. There are two functions that provide the reward. One is a ReceiveLife() function where once the player dies, if they click on the revive button the game restarts and the score is set to score before the player dies instead of 0. The other function is ReceivePoints(), where if the player clicks on the add points button, they are rewarded with 100 extra points. Here are the functions in the game manager script:

public void ReceiveLife()
 {        
   savedScore = (int)playerScore;        
   SceneManager.LoadScene(1); 
 }

public void ReceivePoints()
 {
   playerScore+=100;
   gameOverPanel.gameOverScoreText.text = "Score: " + 
                                           (int)playerScore).ToString();      
 }

Here is the unity ads manager script:

 public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
 {        
  if (showResult == ShowResult.Finished)
   {
    gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
    gameManager.ReceiveLife();
   }

  if (showResult == ShowResult.Finished)
   {
    gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
    gameManager.ReceivePoints();
   }       
  }

Once they watch the ad successfully, both the functions are being called. If the player clicks on the ReceiveLife(), he should only get one extra life and not the additional 100 points and vice-versa.

I'm not sure how to call each function separately. Do I have to create two separate admanagers in order to call these functions or is there a better method?

\$\endgroup\$
6
  • \$\begingroup\$ Is your GameManager still the same after reloading the scene? (DontDestroyOnLoad + singleton) \$\endgroup\$
    – Zibelas
    Commented Jun 22, 2020 at 9:34
  • \$\begingroup\$ Does this question help you? "What is the proper way to handle data between scenes?" - loading the same scene again is also a switch between scenes where you need to take special actions to prevent loss of data. \$\endgroup\$
    – Philipp
    Commented Jun 22, 2020 at 9:40
  • \$\begingroup\$ It looks like you're not correctly passing data between your scenes. Setting the player score on the copy of the game manager in your old scene doesn't do anything to the copy in the new scene. And it doesn't in any way override the playerScore = 0 code you later run in Start() \$\endgroup\$
    – DMGregory
    Commented Jun 22, 2020 at 9:41
  • \$\begingroup\$ is there any way to pass this data between scenes given the game manager script I have or do I have to make a lot of changes to this script? \$\endgroup\$ Commented Jun 22, 2020 at 10:23
  • \$\begingroup\$ @Zibelas I have added an awake method to the script....I don't think its the same game manager.. \$\endgroup\$ Commented Jun 22, 2020 at 10:27

2 Answers 2

0
\$\begingroup\$

A quick and dirty fix would be this:

Make your savedScore a static variable, so it's shared between instances of this class.

static int savedScore = 0;

On startup, copy the saved score into your current score, and reset it for next time.

public void SetupNewGame()
{       
    playerScore = savedScore;
    savedScore = 0;        
    player.transform.position = startLocation.position;              
    UpdateUI(GameStates.Start);
}

Now when you want to persist the score, you save it just before the scene load. If the player doesn't claim the reward, the savedScore stays at zero where we'd reset it to.

public void ReceiveReward()
{        
    savedScore = (int)playerScore;        
    SceneManager.LoadScene(1);    
}

Here I assume that this script is part of the scene that's being unloaded and re-loaded, so you get a fresh instance that runs its own Start() next frame, after the scene has been refreshed.

\$\endgroup\$
1
  • \$\begingroup\$ thanks a lot for the help....... \$\endgroup\$ Commented Jun 23, 2020 at 8:11
0
\$\begingroup\$

The linked question gives you a few suggestions that all work, what is best for your game is for you to decide, how much data you have in other scripts that you need to transfer, etc. If your game is as simple as that, you may get away with a static data holding script.

The why you see score = 0 is, that SceneManager.LoadScene(1); is the same as when you would load the scene for the first time. Your start() is called again, the whole gameManager is a different one (no reference to your saved score, it does not exist anymore).

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .