5

In the game I am creating a 'Game Over' scene which loads once the player loses the game. During the game, the score is counted by the player's position on the screen and increases as the player's y-axis position increases.

I used this code to display the score on the scene the game was actually played:

using UnityEngine;
using UnityEngine.UI;

public class PlayerScore : MonoBehaviour 
{

    public Transform player;
    public Text scoreText; 

    // Update is called once per frame
    void Update() 
    {
        scoreText.text = player.position.y.ToString("0"); 
    }
}

I tried to use the same coding to display the final score of the player on the 'Game Over' screen. The problem I faced was that I was not able to identify the player on the 'Game Over' scene as the player was not an object or sprite on that scene.

Is there an easy way to reference the player sprite from the previous scene into the final ('Game Over') scene so I can use it to determine the final score?

This is the script I tried with a game object of the 'EndScene' within the playing scene:

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

public class EndMenu: MonoBehaviour 
{

    public Text scoreText;
    public Transform player;
    public static bool GameEnds = false;
    public GameObject endMenuUI;

    void OnCollisionEnter2D(Collision2D exampleCol) 
    {
        if(exampleCol.collider.tag == "Obstacle")
        {
            endMenuUI.SetActive(true);
            Time.timeScale = 0.0001f;
            GameEnds = true;
        }
    }

    public void Retry()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex - 1);
    }

    public void BackToMenu()
    {
        SceneManager.LoadScene("Menu");
    }

    public void Quit()
    {
        Debug.Log("Quitting game...");
        Application.Quit();
    }

    // Update is called once per frame
    void Update()
    {
        scoreText.text = player.position.y.ToString("0");
    }
}
derHugo
  • 83,094
  • 9
  • 75
  • 115
Cem Ozsoy
  • 49
  • 1
  • 6
  • You want to pass player sprite from playing scene to game over scene? – MBS Feb 22 '18 at 11:03
  • @bilal1409 Ideally I would like to pass over the final position of the player (which is the score) over into the final game over scene which I will later display on the score text I created. – Cem Ozsoy Feb 22 '18 at 11:06
  • Define public static Sprite like this solution https://stackoverflow.com/questions/42393259/load-scene-with-param-variable-unity – MBS Feb 22 '18 at 11:07
  • @bilal1409 I have check solution. However, I am fairly new to c# and unity coding and was hoping for a more simple solution. Would there be a simpler way of just coding a separate script to display the final position of the player on the end screen? – Cem Ozsoy Feb 22 '18 at 11:25
  • Can you see https://docs.unity3d.com/ScriptReference/Object.DontDestroyOnLoad.html it can help you – MBS Feb 22 '18 at 11:33

3 Answers3

1

You can keep the player using DontDestroyOnLoad

You could add this to the player:

void Awake() {
    DontDestroyOnLoad(transform.gameObject);
}

You could do other stuff like keeping just the data... but the easier way should be this one.

Keep in mind that the player will remain in you gameover screen.

In my opinion the best idea could be creating a new gameobject in your game scene called "GameOverScreen" and disable it until you need it.

derHugo
  • 83,094
  • 9
  • 75
  • 115
Chopi
  • 1,123
  • 1
  • 12
  • 23
  • I tried the idea of creating a game object and disabling it until I need it. However, now the collision script no longer works and the game actually does not end. – Cem Ozsoy Feb 22 '18 at 12:11
  • This is the collision script I used within the 'EndMenu' script I had: void OnCollisionEnter2D(Collision2D exampleCol) { if(exampleCol.collider.tag == "Obstacle") { endMenuUI.SetActive (true); Time.timeScale = 0f; GameEnds = true; } } – Cem Ozsoy Feb 22 '18 at 12:12
  • Why are you setting the timeScale to zero? Can you try to leave it at 0.0001f and check that everything still works? Edit: I understand you are using the timeScale to stop the game completely but I think that it's making you issue. Add a button in the endMenuUI that calls to a funcion that sets again timeScale =1.0f – Chopi Feb 22 '18 at 12:27
  • I changed it from 0f to 0.0001f but everything seemed to remain the exact same. Is there a way I can show you the whole script? – Cem Ozsoy Feb 22 '18 at 12:40
  • Did you try to not destroy the gameobject and changing to your gameover scene? – Chopi Feb 22 '18 at 12:42
  • I edited my original post with the script I used for this. I am pretty sure I do not destroy anything within the script. – Cem Ozsoy Feb 22 '18 at 12:51
  • Is still updating the scoreText?? If not check that the script it's runing/in the scene. – Chopi Feb 22 '18 at 12:54
  • the score text within the game still updates. I don't know whether the score in the final game over scene updates as the collision no longer takes place. – Cem Ozsoy Feb 22 '18 at 12:59
  • however, the score has nothing to do with my "EndMenu" script. It is located on the first canvas in the scene while the endmenu is a whole separate canvas to itself. – Cem Ozsoy Feb 22 '18 at 13:04
  • This script is attached to the gameobject EndScene which is disabled? – Chopi Feb 22 '18 at 13:04
  • If the script is attached to a disabled gameobject it won't run the code, so it's not doing anything. 2 solutions for this right now: separate the OnCollisionEnter2D which is a game logic part from that script. Other solution just create a new gameobject which is a child of EndScene, this child will contain the UI. Let me know but i think we are there! – Chopi Feb 22 '18 at 13:08
  • Thank you a lot for your help! It ended up working very well. By any chance do you know how I can get the score from actual playing scene to disappear once the Game Over scene loads? – Cem Ozsoy Feb 22 '18 at 13:51
  • Could you mark my awnser as correct? Uhms your last question you can just set the text to an empty text `scoreText.text = "";` Also remember to reset all the game status set the position of the player in the initial position or reload the scene (not the best in terms of usability) – Chopi Feb 22 '18 at 14:33
0

I think the easiest solution would be to simply store the score as a static variable that will persist across scene loads, then manually reset it when you start over. For example:

public class PlayerScore : MonoBehaviour 
{

    public Transform player;
    public Text scoreText; 

    public static string scoreString;

    // Update is called once per frame
    void Update() 
    {
        scoreString = player.position.y.ToString("0");
        scoreText.text = scoreString; 
    }
}

Now you will be able to access scoreString from anywhere in your code and it will be whatever it was when the PlayerScore component last ran its Update(). Then in your EndMenu class, you would simply update your Retry() and BackToMenu() methods like so:

public void Retry()
{
    PlayerScore.scoreString = "0";
    SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex - 1);
}

public void BackToMenu()
{
    PlayerScore.scoreString = "0";
    SceneManager.LoadScene("Menu");
}

And your EndMenu.Update() method becomes the following:

// Update is called once per frame
void Update()
{
    scoreText.text = PlayerScore.scoreString;
}
hanoldaa
  • 616
  • 5
  • 10
0

//try to use playerprefs to save the score

public class PlayerScore : MonoBehaviour 
{

    public Transform player;
    public Text scoreText; 

    // Update is called once per frame
    void Update() 
    {
        scoreText.text = player.position.y.ToString("0"); 
        PlayerPrefs.SetInt("CurrentScore", player.position.y);
    }
}

//for another scene get the value of saved score using playerprefs.getInt

public class EndMenu: MonoBehaviour 
{

    public Text scoreText;
    public Transform player;
    public static bool GameEnds = false;
    public GameObject endMenuUI;

    void OnCollisionEnter2D(Collision2D exampleCol) 
    {
        if(exampleCol.collider.tag == "Obstacle")
        {
            endMenuUI.SetActive(true);
            Time.timeScale = 0.0001f;
            GameEnds = true;
        }
    }

    public void Retry()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex - 1);
    }

    public void BackToMenu()
    {
        SceneManager.LoadScene("Menu");
    }

    public void Quit()
    {
        Debug.Log("Quitting game...");
        Application.Quit();
    }

    // Update is called once per frame
    void Update()
    {
        scoreText.text = PlayerPrefs.GetInt("Score",0);
    }
}
CodeMatrix
  • 2,124
  • 1
  • 18
  • 30
rrsantos
  • 404
  • 4
  • 14