How to save high score? - c#

I am trying to save high score in my game. The high score is updated with the score during play. However, after level restarts, both (current score and high score) becomes zero.
How can I do this? What mistake I am doing?
Here is my code:
Generate
public class Generate : MonoBehaviour
{
private static int score;
public GameObject birds;
private string Textscore;
public GUIText TextObject;
private int highScore = 0;
private int newhighScore;
private string highscorestring;
public GUIText highstringgui;
// Use this for initialization
void Start()
{
PlayerPrefs.GetInt ("highscore", newhighScore);
highscorestring= "High Score: " + newhighScore.ToString();
highstringgui.text = (highscorestring);
InvokeRepeating("CreateObstacle", 1f, 3f);
}
void Update()
{
score = Bird.playerScore;
Textscore = "Score: " + score.ToString();
TextObject.text = (Textscore);
if (score > highScore)
{
newhighScore=score;
PlayerPrefs.SetInt ("highscore", newhighScore);
highscorestring = "High Score: " + newhighScore.ToString ();
highstringgui.text = (highscorestring);
}
else
{
PlayerPrefs.SetInt("highscore",highScore);
highscorestring="High Score: " + highScore.ToString();
highstringgui.text= (highscorestring);
}
}
void CreateObstacle()
{
Instantiate(birds);
}
}
Bird
public class Bird : MonoBehaviour {
public GameObject deathparticales;
public Vector2 velocity = new Vector2(-10, 0);
public float range = 5;
public static int playerScore = 0;
// Use this for initialization
void Start()
{
rigidbody2D.velocity = velocity;
transform.position = new Vector3(transform.position.x, transform.position.y - range * Random.value, transform.position.z);
}
// Update is called once per frame
void Update () {
Vector2 screenPosition = Camera.main.WorldToScreenPoint(transform.position);
if (screenPosition.x < -10)
{
Die();
}
}
// Die by collision
void OnCollisionEnter2D(Collision2D death)
{
if(death.transform.tag == "Playercollision")
{
playerScore++;
Destroy(gameObject);
Instantiate(deathparticales,transform.position,Quaternion.identity);
}
}
void Die()
{
playerScore =0;
Application.LoadLevel(Application.loadedLevel);
}
}

The problem is your variable highScore. It is always 0. In the game you ask
if (score > highScore)
And because you set highScore = 0 while declaring that variable, score is always greater.
My suggestion is that you should declare it without value:
private int highScore;
In Start() you should give it value of saved high-score if it exists, and if it doesn't, give it 0 value:
highScore = PlayerPrefs.GetInt("highscore", 0);
That should work for you.

This line in Start(), won't actually do anything.
PlayerPrefs.GetInt ("highscore", newhighScore);
The second parameter is the default return value, if the given key doesn't exist.
But you're not using the return value for anything.
I think what you meant to do is:
newhighScore = PlayerPrefs.GetInt("highscore");
The default value will be 0, when not set explicitly.

Related

Why is the highscore reset when the game starts again?

I'm trying to make a 2D game in Unity. I'm stuck on the high score part. When the game starts, the score and the high score go together, but when the game ends and I press play again, the high score is reset. what is the reason of this?
Thank you from now.
public Text scoreText;
public Text highscoreText;
private float score = 0;
private float highScore = 0;
public Transform cam;
public GameObject panel;
private bool moveLeft;
private bool moveRight;
private float horizontalMove;
void Update()
{
if (rb.velocity.y > 0 && transform.position.y > score)
{
score = transform.position.y;
}
scoreText.text = Mathf.Round(score).ToString();
if (cam.position.y > transform.position.y + 7f)
{
Time.timeScale = 0;
panel.SetActive(true);
}
if (score > highScore)
{
PlayerPrefs.SetFloat("highScore", highScore);
highscoreText.text = "HIGHSCORE: " + Mathf.Round(score).ToString();
PlayerPrefs.Save();
}
MovementPlayer();
}
public void PlayAgain()
{
PlayerPrefs.GetFloat("highScore");
highscoreText.text = "HIGHSCORE: " + Mathf.Round(highScore).ToString();
SceneManager.LoadScene(0);
}
private void Start()
{
rb = GetComponent<Rigidbody2D>();
moveLeft = false;
moveRight = false;
Time.timeScale = 1;
PlayerPrefs.GetFloat("highScore");
highscoreText.text = highScore.ToString();
}
isn't problem here? You are not update your player prefs with actual score but with old highscore?
if (score > highScore)
{
PlayerPrefs.SetFloat("highScore", highScore);
it should be
PlayerPrefs.SetFloat("highScore", score);

How do I write the code to deduct one hit point?

Working on a Basketball Shooter on a unit. I am doing the part that is responsible for subtracting the cells of life. The part of the code that is responsible for adding points is triggered when you touch the "Bonus" component and adds points, but the next part of the code that is responsible for reducing health does not work. By design, this should happen after the ball does not hit the "Bonus" object and comes into contact with the "Terraine" object. How to write a code so that if there is no touch with the "Bonus" object and then there is a touch with the "Terraine" object, one life point is subtracted?
public GameObject hp3;
public GameObject hp2;
public GameObject hp1;
int score = 0;
int best = 0;
void Awake()
{
rb = GetComponent<Rigidbody>();
col = GetComponent<Collider>();
//instance = this;
}
private void Start()
{
best = PlayerPrefs.GetInt("best", 0);
scoreText.text = "Score: " + score.ToString();
bestScoreText.text = "Best: " + best.ToString();
}
public void Push(Vector2 force)
{
rb.AddForce(force, ForceMode.Impulse);
}
public void ActivateRb()
{
rb.isKinematic = false;
}
public void DesactivateRb()
{
rb.velocity = Vector3.zero;
//rb.angularVelocity = 0f;
rb.isKinematic = true;
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.name == "Terraine")
{
transform.position = new Vector3(Random.Range(-4f, 8f), Random.Range(2f, 7f), -0.2f);
DesactivateRb();
}
}
public void OnTriggerExit(Collider other)
{
if (other.gameObject.name == "Bonus")
{
score += 2;
scoreText.text = "Score: " + score.ToString();
if (best < score)
PlayerPrefs.SetInt("best", score);
}
if (other.gameObject.name != "Bonus")
{
health = health - 1;
}
}
void Update()
{
if (health == 3)
{
hp3.SetActive(true);
hp2.SetActive(false);
hp1.SetActive(false);
}
if (health == 2)
{
hp3.SetActive(false);
hp2.SetActive(true);
hp1.SetActive(false);
}
if (health == 1)
{
hp3.SetActive(false);
hp2.SetActive(false);
hp1.SetActive(true);
}
}
Don't know c#, but would something as simple as this work?
Hard to know without the logic.
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.name == "Terraine")
{
transform.position = new Vector3(Random.Range(-4f, 8f), Random.Range(2f, 7f), -0.2f);
DesactivateRb();
if (flag != 1)
{
health = health - 1;
}
else
{
flag = 0; //reset flag if 1
}
}
}
public void OnTriggerExit(Collider other)
{
if (other.gameObject.name == "Bonus")
{
score += 2;
flag = 1;
scoreText.text = "Score: " + score.ToString();
if (best < score)
PlayerPrefs.SetInt("best", score);
}
}

How to assign a value from another script variable?

I accessing another script but her value is by default null.
I want to increase a score when colliding with the obstacle(+5).
Code:
playerscore.cs
public static class playerscore
{
public static int Score = 0; //static variable
}
TouchControll.cs
public Text scoretext;
void Awake()
{
//when I game quit and reenter the game then display the last score
PlayerPrefs.GetInt("score", playerscore.Score);
//this data on my ram not in harddisk
playerscore.Score = PlayerPrefs.GetInt("score", playerscore.Score);
//last score text update when I Reenter the game
scoretext.text = PlayerPrefs.GetInt("score").ToString();
print(scoretext.text);
//pass a score one scene to another scene
PlayerPrefs.SetInt("score", playerscore.Score);
scoretext.text = ("" + playerscore.Score);
PlayerPrefs.SetInt("score", playerscore.Score);
}
void OnCollisionEnter2D(Collision2D col)
{
//Debug.Log("oncollisionenter");
//when my player reaches the finish line then the score add=100; //work fine
if (col.gameObject.tag == "successfinishtag")
{
playerscore.Score += 100;
PlayerPrefs.SetInt("score", playerscore.Score);
scoretext.text = ("" + playerscore.Score);
//Debug.Log("scoreadd:" + playerscore.Score);
}
}
problem is here
I want the when my player collided with the obstacle then increment my score(+5) but the issue is not increasing my score
obstacle.cs
int incrementscore = 5;
TouchControll touchcontroll;
void Start()
{
GetComponent<TouchControll>();
}
//here player colliding with the obstacle
void OnTriggerEnter2D(Collider2D other)
{
foreach (Transform child in transform)
{
//Debug.Log("Inside foreach");
if (child.tag == "obstacleobject")
{
Animator anim = gameObject.GetComponent<Animator>();
anim.Play("animone");
}
}
playerscore.Score = PlayerPrefs.GetInt("score", playerscore.Score);
print(playerscore.Score);
Debug.Log(touchcontroll); //null
if (touchcontroll!= null)//null by default if(null != null) condition false
{
IncrementScore();
touchcontroll.scoretext.text = playerscore.Score.ToString();
}
}
void IncrementScore()
{
//Debug.Log("Inside Increment score");
playerscore.Score = playerscore.Score + incrementscore;
PlayerPrefs.GetInt("score", playerscore.Score);
//print(PlayerPrefs.GetInt("score", playerscore.Score));
PlayerPrefs.SetInt("score", playerscore.Score);
touchcontroll.scoretext.text = playerscore.Score.ToString();
}
I want the when my player collided with the obstacle then increment my score(+5) but the issue is not increasing my score how to solve the problem plz help.
How to solve this problem??
You're not assigning the result of GetComponent back to anything. Change obstacle.cs:
TouchControll touchcontroll;
void Start()
{
touchcontroll = GetComponent<TouchControll>();
}
However, GetComponent() only returns something if there is an instance of whatever object attached to the current game object. Are obstacle.cs and TouchControll.cs both attached to the current GameObject?
If not GetComponent is not going to work, use FindObjectOfType() instead:
void Start()
{
touchcontroll = FindObjectOfType<TouchControll>();
}
Here are the relevant pages from Unity scripting API for more info:
https://docs.unity3d.com/ScriptReference/GameObject.GetComponent.html
https://docs.unity3d.com/ScriptReference/Object.FindObjectOfType.html
I have used in my game this scenario, where Player collide with coin and it increment coin value smoothly in my case. And I have also noticed there is simple difference with your script from me. U have to used FindObjectOfType<> and also have to called public int incrementscore = 5; Where U didn't use any access modifier. Below also include my code, U can take a look and get the idea. Hopefully this will work for U. thanks
public class CoinScript : MonoBehaviour
{
public int coinValue;
private LevelManager gameLevelManager;
// Start is called before the first frame update
void Start()
{
gameLevelManager = FindObjectOfType<LevelManager>();
}
// Update is called once per frame
void Update()
{
}
void OnTriggerEnter2D(Collider2D other) {
Debug.Log("Triggered");
if (other.tag == "Player")
{
gameLevelManager.AddCoins(coinValue);
Destroy(gameObject);
}
}
}
//In LevelManager scripts
public void AddCoins(int numberOfCoins)
{
coins += numberOfCoins;
coinText.text = "Coins : " + coins;
}
Be simply , no use PlayerPrefs to other place
public static class playerscore
{
public static int Score
{
get { return PlayerPrefs.GetInt("score", 0);}
set { PlayerPrefs.SetInt("score", value); }
}
}

The hazards in my unity game are not spawning

I have a game in which you are a player cube and you have to dodge other cubes as they come through your way. The enemy cubes should spawn because of a script I have called GameController. But the cubes are not spawning. Please Help. (Also whenever my cube gets destroyed the gameover and the restart functions are not working)
I tried Recreating the prefab and the code, but nothing happened. Also, the same code is working in my other games
Here is my code:
void Start()
{
gameOver = false;
restart = false;
restartText.text = "";
gameOverText.text = "";
score = 0;
UpdateScore();
StartCoroutine(SpawnWaves());
}
void Update()
{
if (restart)
{
if (Input.GetKeyDown(KeyCode.R))
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
}
IEnumerator SpawnWaves()
{
yield return new WaitForSeconds(startWait);
while (true)
{
for (int i = 0; i < hazardCount; i++)
{
GameObject hazard = hazards[Random.Range(0, hazards.Length)];
Vector3 spawnPosition = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
Quaternion spawnRotation = Quaternion.identity;
GameObject newSpawn = Instantiate(hazard, spawnPosition, spawnRotation) as GameObject;
yield return new WaitForSeconds(spawnWait);
}
yield return new WaitForSeconds(waveWait);
if (gameOver)
{
restartText.text = "Press 'R' for Restart";
restart = true;
break;
}
}
}
public void AddScore(int newScoreValue)
{
score += newScoreValue;
UpdateScore();
}
void UpdateScore()
{
scoreText.text = "Score: " + score;
}
public void GameOver()
{
gameOverText.text = "Game Over!";
gameOver = true;
}
}
I expect the enemies to spawn but they are not
I have copy and pasted your example code into an example project. In this example your script works as expected, as you already mentioned that it works in other projects.
So in my opinion it has something to do with the inspector values.
Check the following:
Did you checked that your hazardCount is greater than zero?
Is your hazardArray completely filled with prefabs?
(If not that should cause the not-spawning but should also cause a null-reference-exception.)
Another option is that you make a screenshot or provide your values in the inspector somehow, so its possible to reproduce the error.
Offtopic: Your Restart after the gameOver is delayed, because the if(gameOver)-Clause comes after the WaitForSeconds(waveWait). My suggestion is to change it to the following:
public GameObject[] hazards;
public Vector3 spawnValues;
public int hazardCount;
public float spawnWait;
public float startWait;
public float waveWait;
public Text scoreText;
public Text restartText;
public Text gameOverText;
private bool gameOver;
private bool restart;
private int score;
private Coroutine gameRoutine;
void Start()
{
gameOver = false;
restart = false;
restartText.text = "";
gameOverText.text = "";
score = 0;
UpdateScore();
gameRoutine = StartCoroutine(SpawnWaves());
}
void Update()
{
if (restart)
{
if (Input.GetKeyDown(KeyCode.R))
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
}
IEnumerator SpawnWaves()
{
yield return new WaitForSeconds(startWait);
while (true)
{
for (int i = 0; i < hazardCount; i++)
{
GameObject hazard = hazards[Random.Range(0, hazards.Length)];
Vector3 spawnPosition = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
Quaternion spawnRotation = Quaternion.identity;
GameObject newSpawn = Instantiate(hazard, spawnPosition, spawnRotation) as GameObject;
yield return new WaitForSeconds(spawnWait);
}
yield return new WaitForSeconds(waveWait);
}
}
public void AddScore(int newScoreValue)
{
score += newScoreValue;
UpdateScore();
}
void UpdateScore()
{
scoreText.text = "Score: " + score;
}
public void GameOver()
{
gameOverText.text = "Game Over!";
restartText.text = "Press 'R' for Restart";
restart = true;
gameOver = true;
StopCoroutine(gameRoutine);
}
What i have changed here is, that the if-condition is removed and the Coroutine is now stored at Start() and is directly stop as the gameOver() method gets executed. Another option instead of the StopCoroutine() would be to set the condition of your while-loop to while(!gameOver).

Make my counter score save highest score even after app closes

So I am making a rocket app, still early into development. I wrote code that counts a score when I collide with objects. How to make it so it saves my highest score and can display it? As soon as I leave my scene it sets the score back to 0 :( please help thank you!
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class POINTS1 : MonoBehaviour
{
public Text countText;
public Text winText;
private Rigidbody rb;
private int count;
void Start()
{
rb = GetComponent<Rigidbody>();
count = 0;
SetCountText();
winText.text = "";
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Pickup"))
{
other.gameObject.SetActive(false);
count = count + 100;
SetCountText();
}
if (other.gameObject.CompareTag("minus300"))
{
other.gameObject.SetActive(false);
count = count -300;
SetCountText();
}
}
void SetCountText()
{
countText.text = "Score: " + count.ToString();
if (count >= 5000)
{
winText.text = "Good Job!";
}
}
}
EDIT: So I tried the code you kindly provided, am I doing something wrong? It doesn't work... I think we might need a GUI element to display the highest score.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class POINTS1 : MonoBehaviour
{
public Text countText;
public Text winText;
private Rigidbody rb;
private int count;
void Start()
{
rb = GetComponent<Rigidbody>();
count = 0;
SetCountText();
winText.text = "";
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Pickup"))
{
other.gameObject.SetActive(false);
count = count + 100;
SetCountText();
}
if (other.gameObject.CompareTag("minus300"))
{
other.gameObject.SetActive(false);
count = count -300;
SetCountText();
}
}
void SetCountText()
{
PlayerPrefs.SetInt("score", count);
PlayerPrefs.Save();
count = PlayerPrefs.GetInt("score", 0);
countText.text = "Score: " + count.ToString();
if (count >= 5000)
{
winText.text = "Good Job!";
}
}
}
//PlayerPrefs.SetInt("score", count);
//PlayerPrefs.Save();
//count = PlayerPrefs.GetInt("score", 0);
What you want is the PlayerPrefs class. PlayerPrefs allows you to store data between sessions of your game.
You can save data by calling PlayerPrefs.Set for any supported data type (int, float or string), and get it by using the corresponding PlayerPrefs.Get.
For example, if you want to save the score, you can do it like so.
PlayerPrefs.SetInt("score", count);
PlayerPrefs.Save();
And get it back by
count = PlayerPrefs.GetInt("score", 0);

Categories