In the current state of our game, we can defeat the enemy, however we can never lose.
Today on 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:
- Set
Width
of Fill
to be 0
- 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:
- 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. - Next, we create a
public Health
to represent our max health
and _currentHealth
to represent how much health our player has. - In
Start()
, we instantiate our _currentHealth
to be our max health
. - 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:
- We have a trigger collider that detects when our knight should start attacking.
- Then we have a mesh collider on our player that will detect when we’re touching the player.
- 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 on 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
CodeProject
The post Day 19 Creating Player Health System and Health UI in Unity appeared first on Coding Chronicles.