When I get my game over the scene the score still remains when a start a new game:
ScoringSYstem.cs
public GameObject scoreText;
public static int theScore;
void Update()
{
scoreText.GetComponent<Text>().text = "Score: " + theScore;
}
Timer.cs
public string LevelToLoad;
public static float timer1 = 30f;
private Text timerSeconds;
public GameObject scoreText;
public static int theScore;
// Use this for initialization
void Start ()
{
timerSeconds = GetComponent<Text> ();
}
// Update is called once per frame
void Update ()
{
timer1 -= Time.deltaTime;
timerSeconds.text = timer1.ToString("f0");
if (timer1 <= 0)
{
timer1 = 30f;
Application.LoadLevel (LevelToLoad);
}
}
How does it in order to reset the score whenever a scene changes?
First of all you need to create an empty GameObject that you call GameManager then you add a Script to it that you call GameManager as well. So that you can acces your Score from everywhere.
public int score = 0;
public static int time = 30;
#region Singelton
public static GameManager instance;
void Awake()
{
if (instance != null)
{
Debug.LogWarning("More than one Instance of Inventory found");
return;
}
instance = this;
}
#endregion
public void GameOver()
{
score = 0;
scoreText.GetComponent<Text>().text = "Score: " + gm.score;
}
Then you can call theese variables from everywhere and change them as well:
GameManager gm;
void Start()
{
gm = GameManager.instance;
}
void Update()
{
if (time >= 0)
gm.GameOver();
}
You may use the
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
method in your gameover scene to reset theScore variable in your GameObject that holds the variable, if the GameOver scene using a GameEngineObject of some kind.
Unity Doc SceneManager
Related
I don't know why the sound is not playing when the game is over. I am able to play sounds on the game menu and when the game start but when the game is over the sound doesn't play.
I am sure I am making some mistake, but I am not able to find where i am doing wrong.
Any help will be appreciated.
Here is the code
public static GameManager instance;
public GameObject PlatformSpawner;
public GameObject GameTapTextPanel;
public GameObject GameIntroPanel;
public GameObject scoreManagerUI;
public bool gameStarted;
public bool gameEnd;
// Start is called before the first frame update
public Text scoreText;
public Text highScoreText;
int score = 0;
int highScore;
AudioSource audioSource;
public AudioClip[] GameMusic;
void Awake()
{
if (instance == null)
{
instance = this;
}
audioSource = GetComponent<AudioSource>();
}
void Start()
{
highScore = PlayerPrefs.GetInt("HighScore");
highScoreText.text = "Best Score : " + highScore;
}
// Update is called once per frame
void Update()
{
if (!gameStarted)
{
if (Input.GetMouseButtonDown(0))
{
GameStart();
audioSource.clip = GameMusic[1];
audioSource.Play();
}
}
}
public void GameStart()
{
gameStarted = true;
PlatformSpawner.SetActive(true);
StartCoroutine(ScoreUp()); // to update the score we need to add this code;
GameTapTextPanel.SetActive(false);
scoreManagerUI.SetActive(true);
GameIntroPanel.GetComponent<Animator>().Play("TwistTurnAnim");
}
public void GameOver()
{
audioSource.clip = GameMusic[3]; //Here is the problem the sound doesn't play
audioSource.Play();
gameStarted = false;
gameEnd = true;
PlatformSpawner.SetActive(false);
scoreManagerUI.SetActive(true);
GameIntroPanel.SetActive(false);
SaveHighScore();
Invoke("ReloadLevel",1f);
StopCoroutine(ScoreUp());
}
void ReloadLevel()
{
SceneManager.LoadScene("Game");
}
//this one is used to increase score per second of the game;
IEnumerator ScoreUp()
{
while (true)
{
yield return new WaitForSeconds(1.5f);
score ++;
scoreText.text = score.ToString();
}
}
public void IncrementScore()
{
audioSource.PlayOneShot(GameMusic[2],0.4f);
score += 4; //Bonus points for game
scoreText.text = score.ToString();
}
void SaveHighScore()
{
if (PlayerPrefs.HasKey("HighScore"))
{
if (score > PlayerPrefs.GetInt("HighScore"))
{
PlayerPrefs.SetInt("HighScore", score);
}
}
else
{
PlayerPrefs.SetInt("HighScore",score);
}
}
Is the audio source part of an object that is deleted upon the Game Over condition?
The scripting API mentions that AudioSource is attached to an object.
In your method, GameOver, you are calling Invoke("ReloadLevel",1f) which will reload the scene in 1.0 seconds. Your GameMusic[3] is not playing because it doesn't have a chance to play before the scene is reloaded.
I have a timer.cs that has 30 sec and i want to add like 4 more sec whenever i get a point. The script that detects is ScoringSystem.cs
ScoringSystem.cs
public class ScoringSystem : MonoBehaviour {
public GameObject scoreText;
public static int theScore;
void Update()
{
scoreText.GetComponent<Text>().text = "Score: " + theScore;
}
}
Timer.cs
public class Timer : MonoBehaviour
{
public string LevelToLoad;
private static float timer = 30f;
private Text timerSeconds;
// Use this for initialization
void Start ()
{
timerSeconds = GetComponent<Text> ();
}
// Update is called once per frame
void Update ()
{
timer -= Time.deltaTime;
timerSeconds.text = timer.ToString("f0");
if (timer <= 0)
{
timer = 30f;
Application.LoadLevel (LevelToLoad);
}
}
}
There's the update on how the ScoringSystem works. https://prnt.sc/t7xk8l
Add this code under the if-statement in the CollectPoint.cs:
Timer.timer += 4;
And change the timer variable from private static float timer = 30f; to public static float timer = 30f;
I have a script that gives you 1 point every 1 second.
I was wondering how to save the score as a high score. I know about PlayerPref, but I can't get my head around it. I've also tried out several other explanations.
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class score : MonoBehaviour
{
private Text scoreText;
private float PIPS;
public GameObject gameOverScore;
public GameObject Player;
public static float scoreAmount;
public void Start()
{
scoreText = GetComponent<Text>();
scoreAmount = 0.0f;
PIPS = 1.0f;
}
public void Update()
{
if (Player.activeInHierarchy == true)
{
scoreText.text = scoreAmount.ToString("F0");
scoreAmount += PIPS * Time.deltaTime;
}
else
{
scoreText.enabled = false;
gameOverScore.GetComponent<TextMeshProUGUI>().text = scoreAmount.ToString("F0");
}
}
}
Here is an Instance from one of my Scripts -->
int HighScore = PlayerPerfs.GetInt("HighScore", 0) //If playing First Time Score = 0
void Save()
{
if(ScoreUpdate.CurrentScore > HighScore) //Check if CurrentScore is more than HighScore
{
PlayerPrefs.SetInt("HighScore", ScoreUpdate.CurrentScore);//Save New High Score
}
}
You Now Just Need To Call This Function Save() whenever the Game get complete or player dies (if dies at any point)
Edit : Replace Your Variables on place of ScoreUpdate
While this is not the ideal way, you can use playerprefs on Awake and OnDisable().
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class score : MonoBehaviour
{
private Text scoreText;
private float PIPS;
public GameObject gameOverScore;
public GameObject Player;
public static float scoreAmount;
public float HighScore;
public void Start()
{
scoreText = GetComponent<Text>();
scoreAmount = 0.0f;
PIPS = 1.0f;
}
private void OnDisable()
{
// this will save the highscore in playerprefs when the game ends[application quit].
PlayerPrefs.SetFloat("HighScore", HighScore);
}
private void Awake()
{
// this will load the highscore from playerprefs
HighScore = PlayerPrefs.GetFloat("HighScore");
}
public void Update()
{
if (Player.activeInHierarchy == true)
{
scoreText.text = scoreAmount.ToString("F0");
scoreAmount += PIPS * Time.deltaTime;
if (scoreAmount > HighScore)
{
HighScore = scoreAmount;
}
}
else
{
scoreText.enabled = false;
gameOverScore.GetComponent<TextMeshProUGUI>().text = scoreAmount.ToString("F0");
}
}
}
let me know if this helps.
I have made a game manager making sure my data gets passed on from the first scene on to the next scene. Within the game manager, I have added certain scripts to ensure it gets passed. As you can see in the picture underneath.
The problem is that the score adds up at the first level, let's say I have 5 points. I go to level 2 and the UI shows my score as 0 (even tho I have nothing put as text within the score text) I kill 1 monster and the UI shows 6. So how can I put the UI to be showing it at all times? (Constant refresh?)
The second problem is that while the score manager does work. The health script cancels everything out when switching levels.
The user starts with 10 health. Takes damage in the first scene, but in the second scene, the user still has 10 health for some reason?
Game Manager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour {
public ActionButton PopupPrefab;
private ActionButton currentlySpawnedPopup;
public static GameManager instance = null;
void Awake () {
if (instance == null) {
instance = this;
} else if (instance != this) {
Destroy (gameObject);
}
Application.targetFrameRate = 60;
}
void Update () {
//if (Input.GetKeyDown(KeyCode.R)) {
// RestartScene ();
//}
}
public void InvokeRestartScene (float time) {
Invoke ("RestartScene", time);
}
public void RestartScene () {
SceneManager.LoadScene (0);
}
public void SpawnPopup (Vector2 position) {
DespawnPopup ();
currentlySpawnedPopup = Instantiate (PopupPrefab, position, Quaternion.identity) as ActionButton;
}
public void DespawnPopup () {
if (currentlySpawnedPopup != null) {
currentlySpawnedPopup.DestroySelf();
currentlySpawnedPopup = null;
}
}
public void FadePopup () {
if (currentlySpawnedPopup != null) {
currentlySpawnedPopup.FadeMe ();
currentlySpawnedPopup = null;
}
}
}
Score Manager
using UnityEngine;
using System;
using System.Collections;
public class ScoreManager : MonoBehaviour
{
public static ScoreManager Instance { get; private set; }
public int Score { get; private set; }
public int HighScore { get; private set; }
public bool HasNewHighScore { get; private set; }
public static event Action<int> ScoreUpdated = delegate {};
public static event Action<int> HighscoreUpdated = delegate {};
private const string HIGHSCORE = "HIGHSCORE";
// key name to store high score in PlayerPrefs
void Awake()
{
if (Instance)
{
DestroyImmediate(gameObject);
}
else
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
}
void Start()
{
Reset();
}
public void Reset()
{
// Initialize score
Score = 0;
// Initialize highscore
HighScore = PlayerPrefs.GetInt(HIGHSCORE, 0);
HasNewHighScore = false;
}
public void AddScore(int amount)
{
Score += amount;
// Fire event
ScoreUpdated(Score);
if (Score > HighScore)
{
UpdateHighScore(Score);
HasNewHighScore = true;
}
else
{
HasNewHighScore = false;
}
}
public void UpdateHighScore(int newHighScore)
{
// Update highscore if player has made a new one
if (newHighScore > HighScore)
{
HighScore = newHighScore;
PlayerPrefs.SetInt(HIGHSCORE, HighScore);
HighscoreUpdated(HighScore);
}
}
}
Health Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class Health : MonoBehaviour {
public UnityEvent OnTakeDamageEvent;
public UnityEvent OnTakeHealEvent;
public UnityEvent OnDeathEvent;
[Header ("Max/Starting Health")]
public int maxHealth;
[Header ("Current Health")]
public int health;
[Header ("IsDeathOrNot")]
public bool dead = false;
[Header ("Invincible")]
public bool invincible = false;
public bool becomeInvincibleOnHit = false;
public float invincibleTimeOnHit = 1f;
private float invincibleTimer = 0f;
[Header ("Perform Dead Events after x time")]
public float DieEventsAfterTime = 1f;
void Start () {
health = maxHealth;
}
void Update () {
if (invincibleTimer > 0f) {
invincibleTimer -= Time.deltaTime;
if (invincibleTimer <= 0f) {
if (invincible)
invincible = false;
}
}
}
public bool TakeDamage (int amount) {
if (dead || invincible)
return false;
health = Mathf.Max (0, health - amount);
if (OnTakeDamageEvent != null)
OnTakeDamageEvent.Invoke();
if (health <= 0) {
Die ();
} else {
if (becomeInvincibleOnHit) {
invincible = true;
invincibleTimer = invincibleTimeOnHit;
}
}
return true;
}
public bool TakeHeal (int amount) {
if (dead || health == maxHealth)
return false;
health = Mathf.Min (maxHealth, health + amount);
if (OnTakeHealEvent != null)
OnTakeHealEvent.Invoke();
return true;
}
public void Die () {
dead = true;
if (CameraShaker.instance != null) {
CameraShaker.instance.InitShake(0.2f, 1f);
}
StartCoroutine (DeathEventsRoutine (DieEventsAfterTime));
}
IEnumerator DeathEventsRoutine (float time) {
yield return new WaitForSeconds (time);
if (OnDeathEvent != null)
OnDeathEvent.Invoke();
}
public void SetUIHealthBar () {
if (UIHeartsHealthBar.instance != null) {
UIHeartsHealthBar.instance.SetHearts (health);
}
}
}
I have thought of adding the following script on to my Health Script
But then I get the following error messages:
" Cannot implicitly convert type 'int' to 'bool'"
"The left-hand side of an assignment must be a variable, property or indexer"
void Awake()
{
if (health)
{
DestroyImmediate(gameObject);
}
else
{
(int)health = this;
DontDestroyOnLoad(gameObject);
}
}
The problem is that the score adds up at the first level, let's say I have 5 points. I go to level 2 and the UI shows my score as 0 (even tho I have nothing put as text within the score text) I kill 1 monster and the UI shows 6. So how can I put the UI to be showing it at all times? (Constant refresh?)
You can make one of the scripts set the UI text score when the scene is loaded.
void Start(){
// Loads the scoreText on start
scoreText.text = yourCurrentScore.ToString();
// Will work unless it has a "DontDestroyOnLoad" applied to it
}
The second problem is that while the score manager does work. The
health script cancels everything out when switching levels. The user
starts with 10 health. Takes damage in the first scene, but in the
second scene, the user still has 10 health for some reason?
In your health script, you had this:
void Start () {
health = maxHealth;
}
This resets your health everytime the scene loads and starts (Aka when you load to the next level). This causes the issue.
" Cannot implicitly convert type 'int' to 'bool'"
if (health)
The () for the if statement should be a condition (a question).
For example, doing health < 0 is valid since its saying "Is health less than 0?"
Doing health is not, since its just saying "10" (or some number).
"The left-hand side of an assignment must be a variable, property or
indexer"
(int)health = this;
If you wanted to change the value of health, just do health = 10 or health = some_Variable_That_Is_An_Integer
I'm having trouble with some countdown timer functionality. In my GameManager script I'm checking the scene name and checking for idle usage (no mouse movement/no clicking) and kicking off a function in my CountdownTimer script that is counts down the amount of idle time using the function StartPreCountTimer(). Once that timer reaches zero it then instantiates a countdown dialog and kicks off IEnumerator RunTimer() that the user can either cancel to continue playing or let reach zero, at which point the game resets and returns to the intro screen.
The problem I'm having is at the precount step. The GameManager script keeps calling StartPreCountTimer() every frame which obviously prevents the countdown from ever completing because it restarts every frame. How do I fix this? How do a call the function only once from Update?
GameManager Script
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
public static GameManager gameManagerInstance = null; // Create Singleton
public GameObject loader;
public GameObject countdownTimer;
public Color defaultBackgroundColor;
public Object startingScene;
public GameObject timeOutWarningDialog;
public float countdownLength;
public float countdownDelay;
private Vector3 prevMousePosition;
private CountdownTimer countdownInstance;
private Scene currentScene;
private GameObject gameManager;
private GameObject canvas;
public static string animalDataFilePathJSON;
public static string animalDataFilePathTex;
void Awake()
{
if (gameManagerInstance == null)
gameManagerInstance = this;
else if (gameManagerInstance != null)
Destroy(gameObject);
DontDestroyOnLoad(gameObject);
gameManager = GameObject.FindGameObjectWithTag("GameManager");
// get and store JSON and Tex filepaths defined in Loader script
animalDataFilePathJSON = GameObject.FindGameObjectWithTag("Loader").GetComponent<Loader>().animalDataFilePathJSON;
animalDataFilePathTex = GameObject.FindGameObjectWithTag("Loader").GetComponent<Loader>().animalDataFilePathTex;
}
void Start()
{
prevMousePosition = Input.mousePosition;
currentScene = SceneManager.GetActiveScene();
countdownInstance = countdownTimer.GetComponent<CountdownTimer>(); // Create an instance of CountdownTimer
}
void Update()
{
currentScene = SceneManager.GetActiveScene();
if (currentScene.name != startingScene.name)
{
countdownInstance.StartPreCountTimer(); // Start Pre-count Timer
if (Input.GetMouseButtonDown(0) || Input.mousePosition != prevMousePosition)
{
countdownInstance.StartPreCountTimer(); // Start Pre-count Timer
if (timeOutWarningDialog != null)
timeOutWarningDialog.SetActive(false);
}
prevMousePosition = Input.mousePosition;
}
}
}
CountdownTimer Script
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class CountdownTimer : MonoBehaviour {
public GameObject timeOutWarningDialog;
public float countdownLength;
public float countdownDelay;
public Object startingScene;
private float countdownInterval = 1;
private GameObject countdownTimer;
private IEnumerator counter;
private Button stopCountButton;
private Text timerTextField;
private GameObject timerInstance;
private GameObject canvas;
// GAME TIMER
public void StartPreCountTimer()
{
CancelInvoke();
if (GameObject.FindGameObjectWithTag("Timer") == null)
Invoke("ShowRestartWarning", countdownDelay);
}
void ShowRestartWarning()
{
canvas = GameObject.FindGameObjectWithTag("Canvas");
timerInstance = Instantiate(timeOutWarningDialog); // instantiate timeout warning dialog
timerInstance.transform.SetParent(canvas.transform, false);
timerInstance.SetActive(true);
Text[] textFields = timerInstance.GetComponentsInChildren<Text>(true); // get reference to timer textfields
timerTextField = textFields[2]; // access and assign countdown textfield
stopCountButton = timerInstance.GetComponentInChildren<Button>(); // get reference to keep playing button
stopCountButton.onClick.AddListener(StopTimer); // add button listener
if (timerInstance.activeSelf == true)
{
counter = RunTimer(countdownLength); // create new reference to counter, resets countdown to countdownLength
StartCoroutine(counter);
}
}
IEnumerator RunTimer(float seconds)
{
float s = seconds;
while (s > -1)
{
if (timerTextField != null)
timerTextField.text = s.ToString();
yield return new WaitForSeconds(countdownInterval);
s -= countdownInterval;
}
if (s == -1)
{
RestartGame();
}
}
void StopTimer()
{
StopCoroutine(counter);
Destroy(timerInstance);
}
void RestartGame()
{
SceneManager.LoadScene(startingScene.name);
}
}