Health Bar UI Issues [SOLVED]

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);
    }
}


There’s the inspector.

(FIXED…kinda)That’s what the debugger says after the player has respawned and the health bar remains zero’d.

Major thanks to anyone willing to lend me a hand, I’ll owe you one.
Also, hey community, nice to meet you all.

Could you edit your post and repaste the code with proper formatting? It’s just too difficult to read like it is.

1 Like

As soon as I noticed I started editing it haha.

Just cut and paste the code from the editor again - best not to edit anything.

1 Like

Ah okay had to “Paste and Match Style” to get it to retain formatting. Sorry.

Can you add this:

    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");
        }

    }

Just to make sure that that isn’t the cause.

1 Like

I’ve inserted that and still continued to have the same problem. Added the debug console to OP thumbnails.

What are those unassigned reference exceptions? You need to fix them first.

It seems your health bar reference is not set properly in the inspector (the reference in this script). Make sure it’s set correctly first.

1 Like

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.

1 Like

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.

1 Like

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!

I look forward to being a part of this community.