Reputation: 17
I'm working on health Bar in my game. As and when my player gets hit by the bullet its life gets reduced by 1 and Im starting a coroutine in which Im setting health bar visibility on/off. But what I want is when player is continuously get hit by the bullets the health bar should not get disable. It should be on. Here what I have done so far is :
IEnumerator EnableAndDisableHealthBar()
{
isHealthBarVisible = true;
showIsHealthBarVisible = true;
fillAmt -= 0.05f;
if (fillAmt >= 0.6f && fillAmt <= 1.0f)
{
HealthBarFiller.color = Color.green;
}
else if (fillAmt >= 0.3f && fillAmt < 0.6f)
{
HealthBarFiller.color = Color.yellow;
}
else if (fillAmt < 0.3f)
{
HealthBarFiller.color = Color.red;
}
yield return new WaitForSeconds(healthBarVisibilityTime);
showIsHealthBarVisible = false;
isHealthBarVisible = false;
}
public void OnTriggerEnter(Collider obj)
{
if (obj.tag == "EnemyBullets")
{
Debug.Log("Player Plane hit by Enemy Bullet");
planeCurrentLife--;
if (planeCurrentLife >= 1 && planeCurrentLife < 20)
{
StartCoroutine(EnableAndDisableHealthBar());
}
else if (planeCurrentLife <= 0)
{
Destroy(obj.gameObject);
StartCoroutine(EnableAndDisableHealthBar());
Explode();
}
}
}
I want to pause my coroutine function when bullets are continuously hits the player so that my health bar will be visible for that whole period of time and it just show the reducing life.
Upvotes: 1
Views: 548
Reputation: 440
I updated your code so that the EnableAndDisableHealthBar()
function is stored as a global field and then stopped (before it finishes and disables the health bar) if it is called again in the OnTriggerEnter()
function. I added comments above the code that I added.
// Store the Coroutine as a global field
Coroutine enableDisableHealthBarCoroutine;
IEnumerator EnableAndDisableHealthBar()
{
isHealthBarVisible = true;
showIsHealthBarVisible = true;
fillAmt -= 0.05f;
if (fillAmt >= 0.6f && fillAmt <= 1.0f)
{
HealthBarFiller.color = Color.green;
}
else if (fillAmt >= 0.3f && fillAmt < 0.6f)
{
HealthBarFiller.color = Color.yellow;
}
else if (fillAmt < 0.3f)
{
HealthBarFiller.color = Color.red;
}
yield return new WaitForSeconds(healthBarVisibilityTime);
showIsHealthBarVisible = false;
isHealthBarVisible = false;
}
public void OnTriggerEnter(Collider obj)
{
if (obj.tag == "EnemyBullets")
{
Debug.Log("Player Plane hit by Enemy Bullet");
planeCurrentLife--;
// Check if there was a previous coroutine running
if(enableDisableHealthBarCoroutine != null)
{
// If there was, then stop it
// (this will leave the health bar enabled)
enableDisableHealthBarCoroutine.StopCoroutine();
}
if (planeCurrentLife >= 1 && planeCurrentLife < 20)
{
// Set the current coroutine to the new instance we're creating here
// This will keep the health bar enabled for another "healthBarVisibilityTime" seconds
enableDisableHealthBarCoroutine = StartCoroutine(EnableAndDisableHealthBar());
}
else if (planeCurrentLife <= 0)
{
Destroy(obj.gameObject);
// Set the current coroutine to the new instance we're creating here
// This will keep the health bar enabled for another "healthBarVisibilityTime" seconds
enableDisableHealthBarCoroutine = StartCoroutine(EnableAndDisableHealthBar());
Explode();
}
}
}
This works because the StartCoroutine()
function returns a Coroutine
object, and you can stop it from running with StopCoroutine()
. There are other ways to stop coroutines, like calling StopAllCoroutines()
, but storing a reference to the coroutine is usually the safest way to manage them and to not introduce bugs. For more info on coroutines, check out the documentation here
The code below is the same code with a few more edits that I saw along the way. I wanted to show both versions but they should do the same thing.
// Store the Coroutine as a global field
Coroutine enableDisableHealthBarCoroutine;
IEnumerator EnableAndDisableHealthBar() {
// could combine isHealthBarVisible and showIsHealthBarVisible as seen here, but I don't know what else they're doing in your code
isHealthBarVisible = true;
showIsHealthBarVisible = true;
fillAmt -= 0.05f;
if (fillAmt >= 0.6f) { // it shouldn't matter if fillAmt is > 1
HealthBarFiller.color = Color.green;
}
else if (fillAmt >= 0.3f) { // guaranteed that fillAmt < .6 because of the previous if statement
HealthBarFiller.color = Color.yellow;
}
else { // guaranteed that fillAmt < .3 because of the previous if statements
HealthBarFiller.color = Color.red;
}
yield return new WaitForSeconds(healthBarVisibilityTime);
showIsHealthBarVisible = false;
isHealthBarVisible = false;
}
public void OnTriggerEnter(Collider obj)
{
if (obj.tag == "EnemyBullets") {
Debug.Log("Player Plane hit by Enemy Bullet");
planeCurrentLife--;
// Check if there was a previous coroutine running
if(enableDisableHealthBarCoroutine != null) {
// If there was, then stop it
// (this will leave the health bar enabled)
enableDisableHealthBarCoroutine.StopCoroutine();
}
// Set the current coroutine to the new instance we're creating here
// This will keep the health bar enabled for another "healthBarVisibilityTime" seconds
enableDisableHealthBarCoroutine = StartCoroutine(EnableAndDisableHealthBar());
if (planeCurrentLife <= 0) {
Destroy(obj.gameObject);
Explode();
}
}
}
Upvotes: 1