Как я могу продолжить функцию сопрограммы, когда каждый раз происходит столкновение? - PullRequest
1 голос
/ 09 апреля 2019

Я работаю над баром здоровья в моей игре.Когда мой игрок попадает под пулю, его жизнь уменьшается на 1, и я запускаю сопрограмму, в которой я включаю / выключаю видимость панели здоровья.Но что я хочу, так это то, что когда игрок постоянно попадает под пули, панель здоровья не должна отключаться.Это должно быть включено.Вот что я сделал до сих пор:

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

Я хочу приостановить свою функцию сопрограммы, когда пули непрерывно попадают в игрока, так что мой индикатор здоровья будет виден в течение всего этого периода времени, и он просто показываетсокращающая жизнь.

1 Ответ

0 голосов
/ 09 апреля 2019

Я обновил ваш код, чтобы функция 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();
        }
    }
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...