Я обновил ваш код, чтобы функция EnableAndDisableHealthBar()
сохранялась как глобальное поле и затем останавливалась (до того, как она завершит работу и отключит индикатор работоспособности), если она вызывается снова в функции OnTriggerEnter()
.Я добавил комментарии к добавленному коду.
// 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();
}
}
}
Это работает, потому что функция StartCoroutine()
возвращает объект Coroutine
, и вы можете остановить его запуск с помощью StopCoroutine()
.Существуют и другие способы остановить сопрограммы, например, вызвать StopAllCoroutines()
, но хранение ссылки на сопрограмму, как правило, является наиболее безопасным способом управления ими и не приводит к ошибкам.Для получения дополнительной информации о сопрограммах, ознакомьтесь с документацией здесь
Код ниже - это тот же код с несколькими другими правками, которые я видел по пути.Я хотел показать обе версии, но они должны делать то же самое.
// 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();
}
}
}