Day 19 Creating Player Health System and Health UI in Unity

Josh Unity VR Development Leave a Comment

In the current state of our game, we can defeat the enemy, however we can never lose.

Today in Day 19, we’re going to start working on the code to fix this.

The first step is that we’re going to create health and a health bar for our player so that we can receive damage and know when we’re going to lose.

Without any delays, let’s get started!

Creating the Health Bar UI

The first thing we should do when creating a health system is to create the UI for our health.

Just like any UI elements, we’ll be using Unity’s UI system to create a health bar, specifically, we’re going to use Unity’s Slider.

We already have an existing UI canvas called: HUD, right click it and select UI -> Slider to create a new Slider. If we don’t have a UI Canvas already, Unity would have automatically created it for us.

We’re going to rename our Slider to Health Bar.

Now you’ll have something like this if we go to 2D mode in our Scene tab with our hierarchy.

We’re going to need to make some adjustments to our slider to make it look nicer.

First off, we don’t need the slider bar. Delete Handle Slider Area.

Next select Health Bar and in the Slider (Script) component range set the Max Value to be 100. Notice a little problem here?

Our value is 0, but our bar is still there. Also, if we were to move our value to 100, the whole bar wouldn’t be filled either.

I found a great answer regarding how to make a slider empty.

To make the adjustments that we want, we have to:

  1. Set Width of Fill to be 0
  2. Go to Fill Area and drag the bar until it fits into the background. In my case, my ending values are Pos X: 75, Width: 160, and the rest is left to its default value.

Here’s what it looks like now:

However now we have another problem, if we were to set the value of the slider to 1, here’s what we would get:

Notice how our fill bar is on the right side of the actual bar itself.

Unfortunately, there doesn’t seem to be an answer that resolved the problem for me. This might be more of a Unity problem than anything else.

However, that doesn’t mean we’ll just give up.

We can simply fix it the same way you might never have noticed it in the Survival Shooter tutorial: we’ll expand the background of the slider so that the bar would naturally look like it’s correct.

To do that, we go to Background and then change Left, Top, Right, and Bottom to -3

After that we should have something like this:

Much better, right? Nothing looks out of place!

Now that we have the health bar looking nicer, it’s time to move it to the bottom left corner. Selecting Health Bar, go to the Rect Transform component, click on the square, to open up the UI alignments and hit Shift+Ctrl and left click the bottom left option to move everything to the bottom left corner.

Right now, everything is exactly at the bottom left corner and doesn’t look nice. Let’s add some adding.

Click Health Bar and set Pox X to be 15 and Pos Y to be 10.

When you’re done, your game should look like this now (don’t forget to set your slider value to be 100)!

Creating our Player Health System

Creating the Player’s health

Now that we have an UI health bar, it’s time to write some code to create the player’s health.

First, click on our Player game object and create a new script called PlayerHealth. This script will control the player health whenever they get damaged and then show these changes in our health bar.

Here’s what our PlayerHealth script looks like:

using UnityEngine;
using UnityEngine.UI;

public class PlayerHealth : MonoBehaviour
{
    public Slider HealthBar;
    public float Health = 100;

    private float _currentHealth;

    void Start ()
    {
        _currentHealth = Health;
    }

    public void TakeDamage(float damage)
    {
        _currentHealth -= damage;
        HealthBar.value = _currentHealth;
    }
}

Here’s how our script works:

  1. We create a public Slider that will be our HealthBar. It’s important to note that we need to import UI otherwise the compiler would complain to us about our Slider object.
  2. Next, we create a public Health to represent our max health and _currentHealth to represent how much health our player has.
  3. In Start() we instantiate our _currentHealth to be our max health.
  4. Finally, we create public TakeDamage(), public meaning that another script can use this component and call the function. Inside this function, we get our damage amount and we update our _currentHealth and we change the value of our slider to reflect health loss.

Before we proceed on, make sure to drag our HealthBar game object to our PlayerHealth script component.

Like so:

Writing the Damage Dealing Code

Now that we have that setup, the next thing we need to do is create the code that calls TakeDamage().

Luckily for us, we already have a script that deals with most of this: EnemyAttack.

All we need to do is grab an instance of our new PlayerHealth script and then run the take damage code.

using UnityEngine;
using System.Collections;


public class EnemyAttack : MonoBehaviour
{
    private Animator _animator;
    private GameObject _player;
    private bool _collidedWithPlayer;

    void Awake()
    {
        _player = GameObject.FindGameObjectWithTag("Player");
        _animator = GetComponent<Animator>();
    }

    void OnTriggerEnter(Collider other)
    {
        if (other.gameObject == _player)
        {
            _animator.SetBool("IsNearPlayer", true);
        }
        print("enter trigger with _player");
    }

    void OnCollisionEnter(Collision other)
    {
        if (other.gameObject == _player)
        {
            _collidedWithPlayer = true;
        }
        print("enter collided with _player");
    }

    void OnCollisionExit(Collision other)
    {
        if (other.gameObject == _player)
        {
            _collidedWithPlayer = false;
        }
        print("exit collided with _player");
    }

    void OnTriggerExit(Collider other)
    {
        if (other.gameObject == _player)
        {
            _animator.SetBool("IsNearPlayer", false);
        }
        print("exit trigger with _player");
    }

    private void Attack()
    {
        if (_collidedWithPlayer)
        {
            _player.GetComponent<PlayerHealth>().TakeDamage(10);
        }
    }
}

In our script, we already have access to the player and detection for when we attack, so all we need to do is grab our PlayerHealth script and trigger our TakeDamage function when we call Attack() in EnemyAttack.

As you might recall from previous tutorials, the way that this code works is that:

  1. We have a trigger collider that detects when our knight should start attacking
  2. Then we have a mesh collider on our player that will detect when we’re touching the player
  3. Finally, in our animation, we set a point in time to call Attack() and when that happens, if the knight is still in contact with our player, we’ll take damage.

With this, we have everything we need to have a complete game, or you might think

If you were to play the game right now, you would have encountered a new problem that hasn’t been realized until now:

If we were to play the game while looking at our console. Whenever we bump into the knight, we would hit OnColliderEnter() get hit, and then for some reason run OnColliderExit() even if we don’t move the player.

As a result, if the player never moves, they’ll only get damaged once. How’s that for being boring?

We’ll solve this tomorrow, because it’s getting late today.

Conclusion

Today in day 19, we created a health system that allows our player to receive damage from our already existing enemy attack code.

We’re almost done, but we’ve encountered a problem where the enemy stops damaging us even when it looks like they successfully attacked us.

I have an idea of what the problem is, but we’ll talk more about that tomorrow!

Day 18 | 100 Days of VR | Day 20

Home

Subscribe To Our Weekly Newsletter!
Like these coding articles? Join my mailing list for the latest updates and influence the code that I write!
We hate spam. Your email address will not be sold or shared with anyone else.

Leave a Reply

Your email address will not be published. Required fields are marked *