Hey guys and gals, I’m trying to create a health bar in my game, I’ve tried a LOT of different things. Perhaps someone else will be able to figure it out?
No matter what I do, when I start the game and the player takes damage his Health Bar instantly drops to zero instead of increments. Even upon death/respawn, it doesn’t restart the health bar at full.
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour {
[System.Serializable]
public class PlayerStats {
public int max_Health = 100;
public int cur_Health = 0;
public GameObject[] Ammo;
}
public PlayerStats playerStats = new PlayerStats();
public int fallBoundary = -20;
public GameObject healthBar;
void Start () {
playerStats.cur_Health = playerStats.max_Health;
InvokeRepeating ("decreasehealth",1f,1f);
}
void Update () {
if (transform.position.y <= fallBoundary)
{
DamagePlayer (999999999);
Debug.Log("PLAYER DEAD - BOUNDARY FALL");
}
if (playerStats.cur_Health <= 0) {
GameMaster.KillPlayer (this);
Debug.Log ("KILL PLAYER");
}
}
public void DamagePlayer (int damage) {
playerStats.cur_Health -= damage;
}
void decreasehealth(){
playerStats.cur_Health -= 10;
float calc_Health = playerStats.cur_Health / playerStats.max_Health;
SetHealthBar (calc_Health);
}
public void SetHealthBar(float myHealth){
healthBar.transform.localScale = new Vector3(myHealth, healthBar.transform.localScale.y, healthBar.transform.localScale.z);
}
}
Fixed that by turning Bar into a Prefab and using the Prefab as the GameObject via Inspector, but then when he dies or takes damage it doesn’t affect the health bar at all.
When your player dies, I assume the actual player object is destroyed and a new one is instantiated. If that’s the case then the new instantiated player object won’t have the reference to the health bar object that exists in your scene (you can probably see this in inspector after a respawn). You would have to make sure that each time you instantiate the player it finds the health bar and it should then be able to affect it again.
Setting the reference to the prefab won’t work because then you aren’t changing anything about the object that exists in scene, you’re only changing the prefab template.
Ah yea it does seem to have that problem… I can’t quite figure out how to fix it though.
When I have my player respawn I use this code in my GameMaster script
public Transform playerPrefab;
public Transform spawnPoint;
public int spawnDelay = 2;
public IEnumerator RespawnPlayer () {
yield return new WaitForSeconds (spawnDelay);
Instantiate (playerPrefab, spawnPoint.position, spawnPoint.rotation);
So I’m guessing I’d need to make another Instantiate line that would recall the Health Bar’s location in the Hierarchy… but I can’t figure out how to do this…
Also that still wouldn’t fix the problem of the health bar simply going from full to empty even if it just takes 1 damage.
After instantiating the new player you can find its Player script and use that to set the health bar reference.
So have your GameMaster script hold the reference to the health bar that exists in the scene and after instantiating the new player, store the gameobject reference returned by the Instantiate call and use GetComponent() on that gameobject to get a reference to the newly instantiated player objects Player script and set the healthBar gameobject reference to the reference that GameMaster holds.
So your GameMaster script:
public GameObject healthBar; //holds reference to scene health bar
....
GameObject newplayer = Instantiate (playerPrefab, spawnPoint.position, spawnPoint.rotation) as GameObject;
newplayer.GetComponent<Player>().healthBar = healthBar;
As for your other problem, I’m not sure. Seems like something is causing the Update on the player to get called before Start() sets your current health to full. You can add a debug to start and see when its called compared to the kill message from Update. Or maybe something else somewhere is changing the value of current health very quickly.
Okay guys! I got the health bar to work perfectly. Thanks immensely to larku and DWilliams, your help was vital in coming to this conclusion.
I’m going to go ahead and post both of my scripts for anyone who comes onto this thread when searching for the same fix.
GameMaster script
using UnityEngine;
using System.Collections;
public class GameMaster : MonoBehaviour {
public GameObject healthBar;
void Start () {
}
public Transform playerPrefab;
public Transform spawnPoint;
public int spawnDelay = 2;
public IEnumerator RespawnPlayer () {
yield return new WaitForSeconds (spawnDelay);
Instantiate (playerPrefab, spawnPoint.position, spawnPoint.rotation);
Debug.Log ("RESPAWN Player");
}
public void KillPlayer (Player player) {
Destroy (player.gameObject);
StartCoroutine (RespawnPlayer());
}
}
Player script
public class Player : MonoBehaviour {
[System.Serializable]
public class PlayerStats {
public GameObject[] Ammo;
}
public PlayerStats playerStats = new PlayerStats();
GameMaster gm;
public int fallBoundary = -20;
public float max_Health = 100f;
public float cur_Health = 0f;
public GameObject healthBar;
void Start () {
healthBar = GameObject.Find ("Bar");
gm = GameObject.FindObjectOfType<GameMaster>();
cur_Health = max_Health;
//InvokeRepeating ("decreasehealth",1f,1f); //Constant Damage Tester
}
void Update () {
if (transform.position.y <= fallBoundary)
{
DamagePlayer (999999999);
Debug.Log("PLAYER DEAD - BOUNDARY FALL");
}
if (cur_Health <= 0) {
gm.KillPlayer (this);
Debug.Log ("KILL PLAYER");
}
float calc_Health = cur_Health / max_Health; // Raito Controller for Health Bar Progress
SetHealthBar (calc_Health);
}
public void DamagePlayer (int damage) {
cur_Health -= damage;
}
//void decreasehealth(){
//cur_Health -= 10; // Constant Damage Tester
//}
public void SetHealthBar(float myHealth){
healthBar.transform.localScale = new Vector3(Mathf.Clamp(myHealth,0,1), healthBar.transform.localScale.y, healthBar.transform.localScale.z);
}
}
Again major thanks to the both of you, and a few others who helped me out!