How to generate random data without repeating in unity C# - c#

Currently i'm developing a quiz kind of game for my gamification project. where i freeze the actual game when the player reaches some score and make question appear. If the answer is correct it will increase the speed of the player.And it will happen in a loop.
Here i'm using loadscene to load the index scene to avoid repeating of questions. The problem here is when the scene is loads it reloads the whole game instead of reloading the quiz part. Is there any way to do it ?
public class GameManager : MonoBehaviour
{
public Question[] facts;
private static List<Question> unansweredfacts;
private Question currentfacts;
[SerializeField]
private Text FactText;
[SerializeField]
private float TimeBetweenFacts = 3f;
[SerializeField]
private Text TrueAnswerText;
[SerializeField]
private Text FalseAnswerText;
[SerializeField]
private Animator animator;
[SerializeField]
public GameObject canvasquiz;
void Start()
{
if (unansweredfacts == null || unansweredfacts.Count == 0)
{
unansweredfacts = facts.ToList<Question>();
}
SetCurrentfact();
Debug.Log(currentfacts.Fact + "is" + currentfacts.IsTrue);
}
void SetCurrentfact()
{
int RandomFactIndex = Random.Range(0, unansweredfacts.Count);
currentfacts = unansweredfacts[RandomFactIndex];
FactText.text = currentfacts.Fact;
if (currentfacts.IsTrue)
{
TrueAnswerText.text = "CORRECT !";
FalseAnswerText.text = "WRONG !";
}
else
{
TrueAnswerText.text = "WRONG !";
FalseAnswerText.text = "CORRECT !";
}
}
IEnumerator TransitionToNextFact()
{
unansweredfacts.Remove(currentfacts);
yield return new WaitForSeconds(TimeBetweenFacts);
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
public void UserSelectTrue()
{
animator.SetTrigger("True");
if (currentfacts.IsTrue)
{
Debug.Log("CORRECT !");
}
else
{
Debug.Log("WRONG !");
}
StartCoroutine(TransitionToNextFact());
}
public void UserSelectFalse()
{
animator.SetTrigger("False");
if (!currentfacts.IsTrue)
{
Debug.Log("CORRECT !");
}
else
{
Debug.Log("WRONG !");
}
StartCoroutine(TransitionToNextFact());
}

Loading the scene again basically restarts it, what you want to do is change the TransitionToNextFact method in the following manner
IEnumerator TransitionToNextFact()
{
unansweredfacts.Remove(currentfacts); // remove the last shown question for the list
canvasquiz.SetActive(false); // disables the quiz canvas until the next question
yield return new WaitForSeconds(TimeBetweenFacts);
SetCurrentfact(); // sets the next random question from the list
canvasquiz.SetActive(true); // show the quiz canvas along with the new question
}
i would also combine the two methods UserSelectTrue and UserSelectFalse into one
public void UserSelected(bool isTrue)
{
animator.SetTrigger(isTrue ? "True" : "False");
if (currentfacts.IsTrue == isTrue)
{
Debug.Log("CORRECT !");
}
else
{
Debug.Log("WRONG !");
}
StartCoroutine(TransitionToNextFact());
}

Related

C# Coroutine repeating a specific part?

I am making a cookie clicker game for a school project and for my achievement system I want to have a simple animation pop up, and text in a separate menu script that already works perfectly fine.
The issue I am having is that the first two achievements work fine, but after the second one pops up, it just repeats with "Test B" and "Test C" repeating infinitely in the console.
I've tried to have values try to make an 'if' statement void but nothing seems to work.
I feel like I am just eating my own tail with all of the Boolean values I created to get this far.
This is my code below, from only a single script in my Unity file.
Hopefully this has enough information needed for guidance.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Achievements : MonoBehaviour
{
[SerializeField] GameObject achievementBanner;
[SerializeField] GameObject achievementText;
[SerializeField] GameObject achievementBannerAnimation;
[SerializeField] GameObject achievementTextAnimation;
[SerializeField] GameObject achiOne;
[SerializeField] GameObject achiTwo;
[SerializeField] GameObject achiThree;
[SerializeField] GameObject achiFour;
[SerializeField] GameObject achiFive;
[SerializeField] GameObject achiSix;
[SerializeField] public static int achiementcount;
bool achievementrec = false;
bool achievementani = false;
bool achidone = false;
// Start is called before the first frame update
void Start()
{
achiOne.SetActive(false);
achiTwo.SetActive(false);
achiThree.SetActive(false);
achiFour.SetActive(false);
achiFive.SetActive(false);
achiSix.SetActive(false);
achievementBanner.SetActive(false);
achievementText.SetActive(false);
achievementText.GetComponent<Text>().text = "Achievement: First cookie!";
}
// Update is called once per frame
void Update()
{
print(achiementcount);
print(achidone);
if (achiementcount == 1)
{
if (!achievementani)
{
if (!achievementrec)
{
print("Test D");
achiOne.SetActive(true);
achievementBanner.SetActive(true);
achievementText.SetActive(true);
StartCoroutine(AchievementGot());
///achidone = true;
}
}
}
if (achidone == true)
{
///print("Test");
///achidone = false;
if (achiementcount == 2)
{
achievementText.GetComponent<Text>().text = "Achievement: First Clicker!";
achievementani = false;
achievementrec = false;
if (!achievementani)
{
if (!achievementrec)
{
print("Test C");
achiTwo.SetActive(true);
achievementBanner.SetActive(true);
achievementText.SetActive(true);
///achidone = true;
StartCoroutine(AchievementGot());
}
}
}
}
///print(achidone);
if (achidone == true)
{
///achidone = false;
if (achiementcount == 3)
{
achievementText.GetComponent<Text>().text = "Achievement: First Upgrade!";
achievementani = false;
achievementrec = false;
if (!achievementani)
{
if (!achievementrec)
{
print("Test A");
achiThree.SetActive(true);
achievementBanner.SetActive(true);
achievementText.SetActive(true);
StartCoroutine(AchievementGot());
}
}
}
}
}
IEnumerator AchievementGot()
{
///achievementrec = true;
achievementBannerAnimation.GetComponent<Animation>().Play("Achievement");
achievementTextAnimation.GetComponent<Animation>().Play("AchiText");
yield return new WaitForSeconds(6);
achidone = true;
print("Test B");
///print(achidone);
achievementBanner.SetActive(false);
achievementText.SetActive(false);
achievementani = true;
achievementrec = true;
///achidone = false;
}
}
First of all you should use a List/Array.
Then you probably also want to show the banner only ONCE when the achievement is unlocked the first time so you should also keep track of which one you already showed.
E.g. something like
[Serializable]
public class Achievement
{
// text to display in the banner
public string Label;
// the object to enable
public GameObject GameObject;
// has this been achieved
public bool Unlocked;
// has this achievement been displayed
public bool Displayed;
}
public class Achievements : MonoBehaviour
{
// in general instead of many GetComponent calls use the correct type right away in the Inspector
[SerializeField] private GameObject achievementBanner;
[SerializeField] private Text achievementText;
[SerializeField] private Animation achievementBannerAnimation;
[SerializeField] private Animation achievementTextAnimation;
[SerializeField] private Achievement[] achievements;
// is currently a display routine running already?
private bool currentlyDisplaying;
private void Start()
{
// initially hide all objects
foreach (var achievement in achievements)
{
achievement.GameObject.SetActive(false);
}
achievementBanner.SetActive(false);
achievementText.gameObject.SetActive(false);
}
private void Update()
{
// if currently a display routine is running do nothing
if (currentlyDisplaying) return;
// otherwise go through all achievements
foreach (var achievement in achievements)
{
// check if one is unlocked but hasn't been displayed yet
if (achievement.Unlocked && !achievement.Displayed)
{
// set to displayed and display it
StartCoroutine(DisplayAchievement(achievement));
// break to only handle one at a time
break;
}
}
}
private IEnumerator DisplayAchievement(Achievement achievement)
{
// just in case if other routine is already running do nothing
if (currentlyDisplaying) yield break;
// block other routines from being started
currentlyDisplaying = true;
// set displayed so it is not displayed again
achievement.Displayed = true;
// Enable your objects and set the text accordingly
achievementText.text = achievement.Label;
achievementText.gameObject.SetActive(true);
achievementBanner.SetActive(true);
achievement.GameObject.SetActive(true);
achievementBannerAnimation.Play("Achievement");
achievementTextAnimation.Play("AchiText");
yield return new WaitForSeconds(6);
achievementBanner.SetActive(false);
achievementText.gameObject.SetActive(false);
// allow the next routine to start
currentlyDisplaying = false;
}
}
even better than poll checking within Update would be to rather go for events like e.g.
[Serializable]
public class Achievement
{
// text to display in the banner
public string Label;
// the object to enable
public GameObject GameObject;
// has this been achieved
// private but (de)serializable e.g. for saving via Json etc later on
// and editable via Inspector
[SerializeField] private bool unlocked = false;
// public read-only access
public bool Unlocked => unlocked;
public void Unlock()
{
// is this already unlocked anyway?
if(!unlocked)
{
// if not unlock and invoke event
unlocked = true;
OnUnlocked?.Invoke(this);
}
}
// global event to subscribe to for all achievement unlocks
public static event Action<Achievement> OnUnlocked;
}
and then listen to this
public class Achievements : MonoBehaviour
{
// in general instead of many GetComponent calls use the correct type right away in the Inspector
[SerializeField] private GameObject achievementBanner;
[SerializeField] private Text achievementText;
[SerializeField] private Animation achievementBannerAnimation;
[SerializeField] private Animation achievementTextAnimation;
[SerializeField] private Achievement[] achievements;
// is currently a display routine running already?
private bool currentlyDisplaying;
// First-In first-out collection to work off the unlocked achievements in the UI
private readonly Queue<Achievement> achievementsToDisplay = new ();
private void Start()
{
// initially hide all objects
foreach (var achievement in achievements)
{
achievement.GameObject.SetActive(false);
}
achievementBanner.SetActive(false);
achievementText.gameObject.SetActive(false);
// listen to the event
Achievement.OnUnlocked += OnAchievementUnlocked;
}
private void OnDestroy()
{
// to avoid exceptions unregister the listener from the event
Achievement.OnUnlocked -= OnAchievementUnlocked;
}
// called everytime an achievement is unlocked
private void OnAchievementUnlocked(Achievement achievement)
{
// add achievement to the queue to work
achievementsToDisplay.Enqueue(achievement);
// if there isn't a worker routine running already anyway
if (!currentlyDisplaying)
{
// start one now
StartCoroutine(DisplayAchievements());
}
}
private IEnumerator DisplayAchievement()
{
// just in case if other routine is already running do nothing
if (currentlyDisplaying) yield break;
// block other routines from being started
currentlyDisplaying = true;
// as long as there are new achievements in the queue simply continue directly with the next one
while(achievementsToDisplay.Count > 0)
{
var achievement = achievementsToDisplay.Dequeue();
// Enable your objects and set the text accordingly
achievementText.text = achievement.Label;
achievementText.gameObject.SetActive(true);
achievementBanner.SetActive(true);
achievement.GameObject.SetActive(true);
achievementBannerAnimation.Play("Achievement");
achievementTextAnimation.Play("AchiText");
yield return new WaitForSeconds(6);
achievementBanner.SetActive(false);
achievementText.gameObject.SetActive(false);
}
// when queue is worked off terminate for now
// and allow the next routine to be started later
currentlyDisplaying = false;
}
}

Sound is not playing After Gameover Unity

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.

Why isn't the number subtracted in PlayerPrefs?

Hello everyone In my code, when you click on the button, a number should be subtracted and saved in PlayerPrefs , the number is subtracted, but does not save . I also learned that the number is saved when you exit the game because of the OnApplicationQuit method, how to make the number normally saved?
public class Chest_Money : MonoBehaviour
{
public int NumCharector;
public int money;
public int Rand;
public Text text;
public GameObject NotMoney;
public GameObject[] Charectors;
public GameObject Panel;
public GameObject Panel2;
public bool bla2;
void Start()
{
money = PlayerPrefs.GetInt("Money_S", 0);
}
private void Awake()
{
}
#if UNITY_ANDROID && !UNITY_EDITOR
private void OnApplicationPause(bool pause){
if(pause){
//PlayerPrefs.SetInt("Money_S" , money);
}
}
#endif
private void OnApplicationQuit()
{
PlayerPrefs.SetInt("Money_S" , money);
}
void Update()
{
PlayerPrefs.SetInt("Money_S", money);
text.text = "$:" + money;
if(bla2 == true){
Panel2.SetActive(true);
}
}
public void Chest(){
if(money >= 100){
money -= 100;
PlayerPrefs.SetInt("Money_S", money);
StartCoroutine(Wait2());
}
else {
NotMoney.SetActive(true);
StartCoroutine(Wait4());
}
}
IEnumerator Wait4(){
yield return new WaitForSeconds(2);
NotMoney.SetActive(false);
}
IEnumerator Wait2()
{
yield return new WaitForSeconds(0);
SceneManager.LoadScene("Scins");
}
}
In general you can/should use PlayerPrefs.Save to force a save on certain checkpoints
By default Unity writes preferences to disk during OnApplicationQuit(). In cases when the game crashes or otherwise prematuraly exits, you might want to write the PlayerPrefs at sensible 'checkpoints' in your game. This function will write to disk potentially causing a small hiccup, therefore it is not recommended to call during actual gameplay.
I then also suggest you rather use a property like
private int _money;
public int money
{
get => _money;
set
{
_money = value;
PlayerPrefs.SetInt("Money_S");
PlayerPrefs.Save();
text.text = "$:" + money;
}
}
So it only updates the text and saves the value once it actually changes.
This way you don't need to update the text or set the value every frame in Update.

Everything breaks after using PlayOneShot

In a game I am working on, the player uses a cube to open doors. When the player interacts with the cube while near the door, the door slides open. I am now trying to make it so that while it slides open, it makes a sound as doors should but I kinda ran into some issues. When I tried to add in the sound for the door, it ignored the part where the door should open altogether.
Here is what I did:
I added an AudioSource to the Cube's child object, CORE because the Cube object already contains an AudioSource which will play at the same time as this sound and assigned it in my Cube's script...
public AudioSource Woosh;
void Start()
{
//Debug.Log("Script initialized!");
Hm = gameObject.GetComponent<AudioSource>();
anim = GameObject.Find("TheFirstDoor").GetComponent<Animator>();
//Door = GameObject.Find("TheFirstDoor").GetComponent<AudioSource>();
Woosh = GameObject.Find("CORE").GetComponent<AudioSource>();
}
Here's the interactive part of the script, it runs a check but for some reason, it is pretending CanBeKey is false...
public void OnActivate()
{
if(HasPlayed == false) //Have I played? Has the Time out passed?
{
HasPlayedFirstTime = true;
Hm.Play();
HasPlayed = true;
PlayTimeOut = 30.0f;
if(CanBeKey == true)
{
anim.Play("Door_Open");
//Door.Play();
StartCoroutine(PlayDaWoosh());
Debug.Log("OPENING!");
}
}
}
Now here is the IEnumerator part of the script, PlayDaWoosh()
IEnumerator PlayDaWoosh()
{
Woosh.PlayOneShot(Woosh.clip);
yield return new WaitForSeconds(Woosh.clip.length);
}
I am aware that the last code snippet is a bit messy but it was the best thing I can think of.
Here is the full script in case you are that curious.....
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CUBE_CORE : MonoBehaviour
{
public AudioSource Hm; // HM!!!
private bool HasPlayed = false;
public float PlayTimeOut = 0.0f;
public static bool CanBeKey = false;
public Animator anim;
public static bool HasPlayedFirstTime = false;
public static AudioSource Door;
public AudioSource Woosh;
// Start is called before the first frame update
void Start()
{
//Debug.Log("Script initialized!");
Hm = gameObject.GetComponent<AudioSource>();
anim = GameObject.Find("TheFirstDoor").GetComponent<Animator>();
//Door = GameObject.Find("TheFirstDoor").GetComponent<AudioSource>();
Woosh = GameObject.Find("CORE").GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
if(HasPlayed == true)
{
if (PlayTimeOut < 0.0f)
{
HasPlayed = false;
}
PlayTimeOut -= Time.smoothDeltaTime;
}
}
public void OnActivate()
{
if(HasPlayed == false) //Have I played? Has the Time out passed?
{
HasPlayedFirstTime = true;
Hm.Play();
HasPlayed = true;
PlayTimeOut = 30.0f;
if(CanBeKey == true)
{
anim.Play("Door_Open");
//Door.Play();
StartCoroutine(PlayDaWoosh());
Debug.Log("OPENING!");
}
}
}
private void OnTriggerEnter(Collider other)
{
if(other.gameObject.name == "SecondDoor")
{
anim = GameObject.Find("DoorSecond").GetComponent<Animator>();
}
if(other.gameObject.name == "ThirdDoor")
{
anim = GameObject.Find("TheThirdDoor").GetComponent<Animator>();
}
if(other.gameObject.name == "FourthDoor")
{
anim = GameObject.Find("TheFourthDoor").GetComponent<Animator>();
}
}
IEnumerator PlayDaWoosh()
{
Woosh.PlayOneShot(Woosh.clip);
yield return new WaitForSeconds(Woosh.clip.length);
}
}
Expected result: Door opening and sound playing
Actual result: Neither happening unless I remove anything that has to do with the Woosh
I apologize ahead of time if I wasn't specific enough or if the question was answered somewhere else. I am relatively new here.

Passing data between scenes Errors

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

Categories