i'm having problem in the score and high score when i play the game and eat coin its increasing the score and high score but when i die and play again its start counting from the score before i dead like i dead my score was 3 when i play again without closing the game its start counting from 3 and the high score aren't saving
Score Manager script
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class ScoreManager : MonoBehaviour
{
public Text scoreText;
public Text hiScoreText;
public static int scoreCount;
public int hiScoreCount;
public bool scoreIncreasing;
// Use this for initialization
void Start()
{
if (PlayerPrefs.HasKey("HighScore"))
{
hiScoreCount = PlayerPrefs.GetInt("HighScore");
}
}
// Update is called once per frame
void Update()
{
if (scoreIncreasing)
{
scoreCount = BallMain.getPoints();
}
if (scoreCount > hiScoreCount)
{
hiScoreCount = scoreCount;
PlayerPrefs.SetFloat("HighScore", hiScoreCount);
}
scoreText.text = "Score: " + (scoreCount);
hiScoreText.text = "High Score: " + (hiScoreCount);
}
}
BallMain Script
using UnityEngine;
using System.Collections;
public static class BallMain {
private static float ballSpeed = 1.2f;
private static int points;
private static int lives = 0;
public enum BallStateEnum { shielded,Vulnerable};
public static BallStateEnum ballState = BallStateEnum.Vulnerable;
public static float getBallSpeed()
{
return ballSpeed;
}
public static void IncreaseSpeed()
{
ballSpeed += 0.1f;
}
public static void IncreasePoints()
{
points++;
}
public static int getPoints()
{
return points;
}
public static int getLive()
{
return lives;
}
public static void addLife()
{
lives++;
}
}
CoinHandler Script
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class coinHandler : MonoBehaviour {
public Transform particles;
void OnCollisionEnter2D(Collision2D collider)
{
if (collider.gameObject.tag == "Player")
{
Instantiate(particles, new Vector3(transform.position.x, transform.position.y, -0.2f), Quaternion.identity);
BallMain.IncreaseSpeed();
BallMain.IncreasePoints();
GameObject.FindWithTag("CoinUI").GetComponent<Text>().text = BallMain.getPoints().ToString();
Destroy(gameObject);
}
}
BadCoinHandler Script
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;
public class BadCoinHandler : MonoBehaviour {
public Transform particles;
// Use this for initialization
void Start ()
{
Destroy(gameObject, 8f);
}
void OnCollisionEnter2D(Collision2D collider)
{
if (collider.gameObject.tag == "Player")
{
Instantiate(particles, new Vector3(transform.position.x, transform.position.y, -0.2f), Quaternion.identity);
Destroy(gameObject);
if(BallMain.getLive() == 0 && BallMain.ballState == BallMain.BallStateEnum.Vulnerable)
{
SceneManager.LoadSceneAsync(0);
}
}
}
}
You have to zero the score manually. Because you are using the static keyword. So create another void in BallMain and make the point zero; Example:
public static void ResetPoints()
{
points = 0;
}
And call it on awake method on Score Manager script; Example:
void Awake()
{
scoreCount = 0; //Also the score here
BallMain.ResetPoints();
}
To save your high score use this:
PlayerPrefs.SetInt("HighScore",scoreCount);//HighScore is key and scoreCount is the number you want to save
PlayerPrefs.Save();
BTW I thing you need another void to reset ball speed as well.
Related
I have class UnitComponent that contains references to every script of the unit. Every unit has scripts UnitUI and UnitStats. So I can access UnitUI methods from UnitStats using UnitComponent class (for example: unitComponent.unitUI.SetHealthUI()). Of course, every script has a reference to UnitComponent class as well to be able to use it. These three scripts have children (PlayerComponent, PlayerUI, PlayerStats). These classes have new methods, for example PlayerUI has SetManaUI() method. But I can't use SetManaUI() using PlayerComponent without creating new variable with PlayerUI class because UnitUI variable doesn't have this method. Is there any option to make new methods accessible through variable unitUI by changing class to PlayerUI or I have to create new PlayerUI variable and somehow get rid of unitUI.
I've tried to make virtual empty method SetManaUI() in UnitUI class and override it in PlayerUI class to make everything work, but it seems like a bad practise because UnitUI can become full of useless empty virtual methods.
Simplified version of scripts
Script that connects scripts together
using UnityEngine;
public class Collector : MonoBehaviour
{
public Stats stats;
public UI ui;
}
UI script
using UnityEngine;
public class UI : MonoBehaviour
{
Collector collector;
public void UIMethod()
{
Debug.Log("UI method");
}
}
Stats script
using UnityEngine;
public class Stats : MonoBehaviour
{
Collector collector;
public void StatsMethod()
{
Debug.Log("Stats method");
}
}
Child of collector script
public class ChildCollector : Collector
{
public string someNewData;
public string someNewData1;
public string someNewData2;
public void Start()
{
ui.ChildUIMethod(); //has to be executed and write "Child UI method"
stats.ChildStatsMethod(); //has to be executed and write "Child Stats method"
}
}
Child of UI script
using UnityEngine;
public class ChildUI : UI
{
ChildCollector childCollector;
public void ChildUIMethod()
{
Debug.Log("Child UI Method");
}
}
Child of Stats script
using UnityEngine;
public class ChildStats : Stats
{
ChildCollector childCollector;
public void ChildStatsMethod()
{
Debug.Log("Child Stats Method");
}
}
Full version of scripts
Unit Component script
using UnityEngine;
public class UnitComponent : MonoBehaviour
{
public Animator animator;
public UnitStats unitStats;
public UnitUI unitUI;
}
UnitStats script
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class UnitStats : MonoBehaviour
{
public UnitComponent unitComponent;
public float maxHealth;
public float health;
public List<GameObject> lootDrop;
protected virtual void Start()
{
if (health <= 0 || health > maxHealth)
health = maxHealth;
unitComponent.unitUI.SetHealthUI(health, maxHealth);
CheckDeath();
}
private void CreateDamagePopup(float takenDamage)
{
GameObject damagePopupCanvas = Instantiate(unitComponent.unitUI.damagePopupCanvasPref, transform.position, Quaternion.identity, transform);
damagePopupCanvas.GetComponentInChildren<Text>().text = takenDamage.ToString();
Vector3 randomPosOffset = new Vector3(Random.Range(-0.1f, 0.1f), Random.Range(-0.1f, 0.1f), 0f);
damagePopupCanvas.transform.position += randomPosOffset;
Destroy(damagePopupCanvas, 3f);
}
public float CalculateHealthPercentage()
{
return (health / maxHealth);
}
protected void CheckDeath()
{
if (health <= 0)
{
unitComponent.animator.SetTrigger("isDead");
DropLoot();
}
}
protected void CheckOverheal()
{
if (health > maxHealth)
{
health = maxHealth;
}
}
public void DealDamage(int damage)
{
unitComponent.unitUI.healthBar.SetActive(true);
health -= damage;
unitComponent.unitUI.SetHealthUI(health, maxHealth);
CheckDeath();
CreateDamagePopup(damage);
}
public void HealCharacter(int heal)
{
health += heal;
CheckOverheal();
unitComponent.unitUI.SetHealthUI(health, maxHealth);
}
public void DropLoot()
{
foreach (GameObject item in lootDrop)
Instantiate(item, transform.position, Quaternion.identity);
}
}
UnitUI script
using UnityEngine;
using UnityEngine.UI;
public class UnitUI : MonoBehaviour
{
public UnitComponent unitComponent;
public GameObject damagePopupCanvasPref;
public GameObject healthBar;
protected Slider healthBarSlider;
virtual public void Start()
{
healthBarSlider = healthBar.GetComponent<Slider>();
}
public virtual void SetHealthUI(float health, float maxHealth)
{
if (healthBarSlider)
healthBarSlider.value = health / maxHealth;
}
public virtual void SetCoinsUI(int coinAmount) { } //Necessary for PlayerUI script working
public virtual void SetManaUI(float mana, float maxMana) { } //Necessary for PlayerUI script working
}
PlayerComponent script
using UnityEngine;
public class PlayerComponent : UnitComponent
{
public PlayerMovement playerMovement;
public PlayerSlot playerSlot;
public Rigidbody2D rb;
}
PlayerStats script
using UnityEngine;
public class PlayerStats : UnitStats
{
protected int coins;
public float mana;
public float maxMana;
public float manaRegenPerSec;
protected override void Start()
{
UI = gameObject.GetComponent<PlayerUI>();
animator = gameObject.GetComponent<Animator>();
if (health <= 0 || health > maxHealth)
health = maxHealth;
UI.SetHealthUI(health, maxHealth);
UI.SetManaUI(mana, maxMana);
CheckDeath();
}
public void Update()
{
if (mana < maxMana)
{
mana += manaRegenPerSec * Time.deltaTime;
UI.SetManaUI(mana, maxMana);
}
}
private void Awake()
{
DontDestroyOnLoad(this);
}
public void AddCoins(int amount)
{
coins += amount;
UI.SetCoinsUI(amount);
}
}
PlayerUI script
using System;
using UnityEngine;
using UnityEngine.UI;
public class PlayerUI : UnitUI
{
[SerializeField] protected GameObject manaBar;
[SerializeField] protected Text manaValue;
[SerializeField] protected Text healthValue;
[SerializeField] protected Text coinValue;
protected Slider manaBarSlider;
public override void Start()
{
healthBarSlider = healthBar.GetComponent<Slider>();
manaBarSlider = manaBar.GetComponent<Slider>();
}
public override void SetHealthUI(float health, float maxHealth)
{
healthBarSlider.value = health / maxHealth;
healthValue.text = health.ToString() + "/" + maxHealth.ToString();
}
public override void SetManaUI(float mana, float maxMana)
{
manaBarSlider.value = mana / maxMana;
manaValue.text = Math.Round(mana).ToString() + "/" + Math.Round(maxMana).ToString();
}
public override void SetCoinsUI(int coinAmount)
{
coinValue.text = coinAmount.ToString();
}
}
I'm new to Unity and together with a few friends, I try to make a game. I was trying to connect the healthbar I made to the damage u can deal by shooting knifes. First to test this I used:
void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse1))
{
TakeDamage(25);
}
}
Everything worked fine and when I pressed Mouse1 the healthbar worked.My goal was, that when a knife hits the enemy 25 damage is dealt and the healthbar shows that the enemy lost health. However, when the knifes hit the enemy nothing happens. Can you please help me because I tried fixing this for like 3 hours and I'm getting kinda frustrated. Thank you.
Here's the code for the healthbar:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class healthbar : MonoBehaviour
{
public Slider slider;
public void SetMaxHealth(int health)
{
slider.maxValue = health;
slider.value = health;
}
public void SetHealth(int health)
{
slider.value = health;
}
}
And here's the code for the enemy:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy_Follow : MonoBehaviour
{
public float speed;
public Transform target;
public int damage = 25;
public int maxHealth = 100;
public int currentHealth;
public healthbar healthBar;
// Start is called before the first frame update
void Start()
{
currentHealth = maxHealth;
healthBar.SetMaxHealth(maxHealth);
target = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse1))
{
TakeDamage(25);
}
transform.position = Vector2.MoveTowards(transform.position, target.position, speed * Time.deltaTime);
}
public void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Knife")
{
TakeDamage(25);
}
}
public void TakeDamage(int damage)
{
currentHealth -= damage;
healthBar.SetHealth(currentHealth);
}
}
After finding out that your colliders are not triggers it should rather be OnCollisionEnter2D like e.g.
public void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Knife"))
{
TakeDamage(25);
}
}
See also Colliders -> Collision Action Matrix
You may try this code to look if the slider works at all. If this code does work (You can change things with the inspector) then it should be an error with the collision/trigger detection and nothing else.
public class SliderTest : MonoBehaviour {
public Slider slider;
public int maxHealth = 100;
private int currentHealth = 100;
public bool resetHealth = false;
public bool damage = false;
void Start() {
slider = GetComponent<Slider>();
SetMaxHealth(maxHealth);
}
void Update() {
if(resetHealth) {
resetHealth = false;
SetHealth(maxHealth);
}
if(damage) {
damage = false;
SetHealth(currentHealth-10);
}
}
public void SetMaxHealth(int health) {
slider.maxValue = health;
slider.value = 100;
}
public void SetHealth(int health) {
currentHealth = health;
slider.value = currentHealth;
}
}
}
Want to make my Spheres able to damage each other
Have tried to get the component of the other object
Health script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class Hitpoints
{
private int health;
public int healthMax;
public Hitpoints(int health)
{
this.health = health;
}
public int GetHealth()
{
return health;
}
public float GetHealthPercent()
{
return (float)health / healthMax;
}
public void Damage(int damageAmount)
{
health -= damageAmount;
if (health < 0)
{
health = 0;
}
}
public void Heal(int healAmount)
{
health += healAmount;
if (health > healthMax)
{
health = healthMax;
}
}
}
Damage script
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Detect_Blue : MonoBehaviour
{
Hitpoints hitpoints = new Hitpoints(100);
bool onetime = false;
public float radius;
public Vector3 direction = new Vector3(2, 2, 2);
private void Start()
{
Debug.Log("Health: " + hitpoints.GetHealth());
InvokeRepeating("DetectEnemy", 4f, 2f);
}
private void DetectEnemy()
{
var hitColliders = Physics.OverlapSphere(direction, radius);
for (var i = 0; i < hitColliders.Length; i++)
{
if (hitColliders[i].CompareTag("Player"))
{
if (!onetime)
{
onetime = true;
print(hitColliders[i].tag);
InvokeRepeating("Hello", 1, 1);
}
}
// collect information on the hits here
}
}
private void Hello()
{
var hitColliders = Physics.OverlapSphere(direction, radius);
for (var i = 0; i < hitColliders.Length; i++)
{
if (hitColliders[i].CompareTag("Player"))
{
hitColliders[i].GetComponent<Hitpoints>().Damage(10);
}
Debug.Log("Damaged: " + hitColliders[i].GetComponent<Hitpoints>().GetHealth());
if (hitpoints.GetHealth() == 0)
{
Destroy(gameObject);
}
}
}
}
ArgumentException: GetComponent requires that the requested component 'Hitpoints' derives from MonoBehaviour or Component or is an interface.
UnityEngine.Component.GetComponent[Hitpoints] () (at C:/buildslave/unity/build/Runtime/Export/Component.bindings.cs:42)
Detect_Blue.Hello () (at Assets/Detect_Blue.cs:57)
When you do GetComponent<T> on a game object, the type of T should inherit from monobehaviour.(Since Monobehavior are components for game-object, and you are trying to get a component)
To fix this, just simply use the hitpoints you have already created in Detect_Blue.
Debug.Log("Damaged: " + hitColliders[i].GetComponent<Hitpoints>().GetHealth());
will become
Debug.Log("Damaged: " + hitColliders[i].GetComponent<Detect_Blue>().hitpoints.GetHealth());
likewise for hitColliders[i].GetComponent<Hitpoints>().Damage(10);, it should be:
hitColliders[i].GetComponent<Detect_Blue>().hitpoints.Damage(10);
Alternatively,
you can just simply make Hitpoints inherit from Monobehavior and attach the script to the respective gameObject.
Though in your case, the first solution will be more feasible.
Also, you can use OnCollisionEnter to detect when the balls enter collision with another object.
I am creating a laser defender game in unity and I have this problem where when I shoot the first enemy it takes me directly to the NextLevelMenu scene but I want it to load when all the enemies are killed(on this level I have 5 enemies to kill). I have been told that I need to send a reference to the instance of its spawner to every spawned enemy but I did not quite understand. Can someone help, please?
EnemySpawner Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EnemySpawner : MonoBehaviour {
[SerializeField] GameObject EnemyPreFab;
[SerializeField] int MaxEnemies = 30;
[SerializeField] float EnemySpawnTime = 1.00001f;
[SerializeField] GameObject FirstWaypoint;
int CurrentNumOfEnemies = 0;
public LevelManager myLevelManager;
public int maximumnumberofhits = 0;
public static EnemySpawner Instance = null;
int timesEnemyHit;
IEnumerator SpawningEnemies()
{
while(CurrentNumOfEnemies <= MaxEnemies)
{
GameObject Enemy = Instantiate(EnemyPreFab, this.transform.position, Quaternion.identity);
CurrentNumOfEnemies++;
yield return new WaitForSeconds(EnemySpawnTime);
}
}
void Start()
{
if (Instance == null)
Instance = this;
StartCoroutine(SpawningEnemies());
timesEnemyHit = 0;
if (this.gameObject.tag == "EnemyHit")
{
CurrentNumOfEnemies++;
}
}
public void OnEnemyDeath()
{
CurrentNumOfEnemies--;
if (CurrentNumOfEnemies < 1)
{
// You killed everyone, change scene:
LaserLevelManager.LoadLevel("NextLevelMenu");
}
}
}
EnemyShooting script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyShooting : MonoBehaviour {
[SerializeField] float EnemyLaserSpeed = 10f;
[SerializeField] float EnemyLaserFireTime;
[SerializeField] GameObject LaserBulletEnemyPreFab;
[SerializeField] int MaxNumberOfHits = 1;
int CurrentNumberOfHits = 0;
Coroutine FireCoroutine;
void OnTriggerEnter2D(Collider2D collider)
{
if(collider.gameObject.tag == "PlayerLaser")
{
if(CurrentNumberOfHits < MaxNumberOfHits)
{
CurrentNumberOfHits++;
Destroy(collider.gameObject);
Score.ScoreValue += 2;//The user will be rewarded 1 point
}
}
}
void DestroyEnemy()
{
if(CurrentNumberOfHits >= MaxNumberOfHits)
{
Destroy(gameObject);
EnemySpawner.Instance.OnEnemyDeath(); // Tell the EnemySpawner that someone died
}
}
private void Fire()
{
FireCoroutine = StartCoroutine(ShootContinuously());
}
void BecomeVisible()
{
Fire();
}
IEnumerator ShootContinuously()
{
while (true)
{
GameObject LaserBulletEnemy = Instantiate(LaserBulletEnemyPreFab, this.transform.position, Quaternion.identity) as GameObject;
LaserBulletEnemy.GetComponent<Rigidbody2D>().velocity = new Vector2(0, EnemyLaserSpeed);
EnemyLaserFireTime = Random.Range(0.5f, 0.9f);
yield return new WaitForSeconds(EnemyLaserFireTime);
}
}
// Use this for initialization
void Start () {
BecomeVisible();
}
// Update is called once per frame
void Update () {
DestroyEnemy();
}
}
I would add a two fields to the spawner script. EnemiesToNextLevel and KilledEnemies. Then in the OnEnemyDeath() of your spawner, you may increase KilledEnemies everytime it is called, and then ask if KilledEnemies >= EnemiesToNextLevel, before changing the scene.
Sure there are a lot of other ways to do it, but for me thats the easiest.
I currently have a 2d platformer, where the player is given 9 lives on start, and loses a life everytime they hit an obstacle.
The GameManager script stores and displays the health and the Entity script updates the health in GameManager if the player loses a life.
If the player loses a life, they can respawn in that level.
On completion of a level, the player goes to a new scene "Level Complete", where they can choose to continue to the next level or quit the game.
However, when the player continues to the next level, the currentHealth variable does not persist and resets to 0.
I know WHY this problem is occurring, but I do not know how to fix it.
currentHealth is not being called anywhere in LevelComplete, so on Start in GameManager, it has lost the value of currentHealth.
I can't call GameManager on LevelComplete because it will spawn the player. So I'm not sure how to pass the variable.
Here are my scripts.
Game Manager
using UnityEngine.UI;
using System.Collections;
public class GameManager : MonoBehaviour {
public GameObject player;
private GameCamera cam;
private GameObject currentPlayer;
private Vector3 checkpoint;
public Text livesText;
private Entity livesCount;
public static int startHealth = 9;
public int currentHealth;
public bool playerDeath = false;
public static int levelCount = 2;
public static int currentLevel = 1;
void Start () {
cam = GetComponent<GameCamera> ();
livesText.text = currentHealth.ToString ();
if(GameObject.FindGameObjectWithTag("Spawn")){
checkpoint = GameObject.FindGameObjectWithTag("Spawn").transform.position;
}
SpawnPlayer (checkpoint);
}
private void SpawnPlayer(Vector3 spawnPos) {
currentPlayer = Instantiate (player, spawnPos, Quaternion.identity) as GameObject;
cam.setTarget(currentPlayer.transform);
}
public void Update(){
if(!currentPlayer){
if (Input.GetButtonDown ("Respawn")) {
playerDeath = false;
SpawnPlayer (checkpoint);
}
}
if (playerDeath) {
Destroy (currentPlayer);
}
if (currentPlayer) {
currentHealth = currentPlayer.GetComponent<Entity> ().GetHealth ();
}
livesText.text = currentHealth.ToString ();
}
public void SetCheckPoint(Vector3 cp){
checkpoint = cp;
}
public void EndLevel(){
if(currentLevel < levelCount){
currentLevel++;
Application.LoadLevel("Level Complete");
}
else{
Application.LoadLevel("Game Complete");
}
}
}
Entity
using UnityEngine;
using System.Collections;
public class Entity : MonoBehaviour {
public static int currHealth;
private int checkHealth; //Make sure 0 < health < 9
public void ModifyHealth(int amount){
checkHealth = currHealth + amount;
if (checkHealth >= 9) {
currHealth = 9; //Health can't be greater than 9
}
else if(checkHealth <= 0){
Die (); //End game if health is less than or equal to 0
}
else{
currHealth = checkHealth; //Otherwise, update Health
}
}
public int GetHealth(){
return currHealth;
}
public void SetHealth(int currentHealth){
currHealth = currentHealth;
}
public void Die(){
Application.LoadLevel ("Game Over");
}
}
Level Complete
using UnityEngine;
using System.Collections;
public class LevelComplete : MonoBehaviour {
public GUISkin gSkin;
void OnGUI(){
GUI.skin = gSkin;
if(GUI.Button(new Rect((Screen.width/2) - Screen.width *0.15f,Screen.height/2 - Screen.height *0.05f,Screen.width*0.3f,Screen.height*0.1f),"Next Level")){
Application.LoadLevel ("Level 2");
}
if(GUI.Button(new Rect((Screen.width/2) - Screen.width *0.15f,Screen.height/2 + 20.0f,Screen.width*0.3f,Screen.height*0.1f),"Quit")){
Application.Quit ();
}
}
}