Остановка корутин
Часть раздела Физика и игровой процесс путешествия по Unity на Coddy. Урок 25 из 63.
StartCoroutine возвращает Coroutine — дескриптор запущенной им сопрограммы. Сохрани его в поле, и StopCoroutine(handle) остановит эту сопрограмму в месте приостановки: строки после её yield никогда не выполнятся. StopAllCoroutines() останавливает все сопрограммы, запущенные скриптом. Нажатие пробела включает и выключает этот сигнал:
Coroutine beeping;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
if (beeping == null)
{
beeping = StartCoroutine(Beep());
}
else
{
StopCoroutine(beeping);
beeping = null;
}
}
}
IEnumerator Beep()
{
while (true)
{
Debug.Log("Beep");
yield return new WaitForSeconds(1f);
}
}Поле не очищается само, когда сопрограмма останавливается, поэтому сигнализация снова присваивает ему значение null, и при следующем нажатии пробела известно, что ничего не выполняется. Два способа, которые кажутся правильными, не работают. StopCoroutine(Beep()) снова вызывает Beep(), создавая новую, ещё не запущенную сопрограмму, и останавливает её, поэтому сигнал продолжает звучать. А enabled = false выключает Update() скрипта, но его сопрограммы продолжают выполняться. Сопрограмма завершается, когда её останавливают с помощью её дескриптора или StopAllCoroutines(), когда она доходит до последней строки либо когда её GameObject деактивируют с помощью SetActive(false) или уничтожают.
Задание
ЛегкоПробел зажигает фитиль Bomb: корутина Fuse выводит в журнал Fuse lit, ждёт fuseTime (3) секунды, выводит Boom и уничтожает бомбу. Щелчок должен обезвредить её, но он выключает скрипт, и бомба всё равно взрывается. Исправь обезвреживание:
- Щелчок, пока горит фитиль, останавливает его и выводит в журнал
Defused. Бомба остаётся. - После этого пробел снова может зажечь фитиль, и на этот раз, если не щёлкать, бомба взорвётся через 3 секунды.
Нажми Играть, зажги фитиль, щёлкни и посмотри на Console, затем нажми Проверить.
Попробуйте сами
using System.Collections;
using UnityEngine;
public class Bomb : MonoBehaviour
{
public float fuseTime = 3f;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
StartCoroutine(Fuse());
}
if (Input.GetMouseButtonDown(0))
{
enabled = false;
Debug.Log("Defused");
}
}
IEnumerator Fuse()
{
Debug.Log("Fuse lit");
yield return new WaitForSeconds(fuseTime);
Debug.Log("Boom");
Destroy(gameObject);
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Физика и игровой процесс
1Твёрдое тело
Гравитация и массаТолкаем с помощью AddForceПрыжок с импульсомFixedUpdate для физикиСкоростьКинематические телаПовторение: пусковая площадка4Корутины
InvokeInvokeRepeating, CancelInvokeВаша первая корутинаЦиклы в корутинахОстановка корутинПовторение: обратный отсчёт2Столкновения
OnCollisionEnterВо что я попал?Разрушение при столкновенииСтояние на землеОтскок и трениеФормы коллайдеровПовторение: разрушаемая стена5Проект: Погоня за монетами
Катящийся мячМонеты для сбора