Какие знаешь yield инструкции?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Yield инструкции в C# для Unity
В Unity разработке yield инструкции — это фундаментальный механизм корутин, позволяющий приостанавливать выполнение функции на одном или нескольких кадрах без блокировки основного потока. Это мощный инструмент для управления временем, асинхронными операциями и последовательностями действий.
Основные типы yield инструкций
1. Yield return null и yield break
// yield return null - приостановка на один кадр
IEnumerator UpdateEveryFrame()
{
while (true)
{
Debug.Log("Выполняется каждый кадр");
yield return null; // Ждем следующий кадр
}
}
// yield break - немедленное завершение корутины
IEnumerator ProcessWithCondition()
{
if (!isValid)
{
Debug.Log("Условие не выполнено, завершаем корутину");
yield break; // Немедленный выход
}
// Дальнейшая логика...
}
2. WaitForSeconds и WaitForSecondsRealtime
IEnumerator DelayedAction()
{
Debug.Log("Начало ожидания");
// Ожидание с использованием масштабированного времени (зависит от Time.timeScale)
yield return new WaitForSeconds(2.5f);
Debug.Log("Прошло 2.5 секунды (масштабированное время)");
// Ожидание с использованием реального времени (не зависит от Time.timeScale)
yield return new WaitForSecondsRealtime(1f);
Debug.Log("Прошла 1 секунда реального времени");
}
3. WaitForEndOfFrame и WaitForFixedUpdate
IEnumerator FrameOperations()
{
// WaitForEndOfFrame - выполнение в конце рендеринга кадра
yield return new WaitForEndOfFrame();
CaptureScreenshot(); // Идеально для скриншотов
// WaitForFixedUpdate - выполнение перед физическим обновлением
yield return new WaitForFixedUpdate();
ApplyPhysicsForce(); // Безопасные операции с физикой
}
4. WaitUntil и WaitWhile (условные ожидания)
IEnumerator WaitForCondition()
{
// Ожидание, пока условие не станет истинным
Debug.Log("Ждем, пока игрок не нажмет Space...");
yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.Space));
Debug.Log("Space нажата!");
// Ожидание, пока условие истинно
yield return new WaitWhile(() => player.IsMoving);
Debug.Log("Игрок остановился");
}
5. Custom Yield Instructions (пользовательские инструкции)
// Создание собственной инструкции ожидания
public class WaitForCustomEvent : CustomYieldInstruction
{
private bool isEventTriggered = false;
public override bool keepWaiting => !isEventTriggered;
public void TriggerEvent()
{
isEventTriggered = true;
}
}
// Использование в корутине
IEnumerator WaitForCustomTrigger()
{
var customWait = new WaitForCustomEvent();
StartCoroutine(TriggerLater(customWait));
yield return customWait; // Ждем, пока событие не сработает
Debug.Log("Событие сработало!");
}
6. AsyncOperation ожидания (для асинхронных операций)
IEnumerator LoadSceneAsync()
{
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync("Level2");
// Ожидание завершения асинхронной загрузки
yield return asyncLoad;
// Или с прогрессом
while (!asyncLoad.isDone)
{
float progress = Mathf.Clamp01(asyncLoad.progress / 0.9f);
Debug.Log($"Прогресс загрузки: {progress * 100}%");
yield return null;
}
}
Практические примеры использования
// Комбинированный пример
IEnumerator ComplexSequence()
{
// Этап 1: Начальная задержка
yield return new WaitForSeconds(1f);
// Этап 2: Ожидание ввода
Debug.Log("Нажмите Enter для продолжения");
yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.Return));
// Этап 3: Анимация в течение нескольких кадров
for (int i = 0; i < 60; i++) // Примерно 1 секунда при 60 FPS
{
objectToAnimate.transform.Rotate(0, 6f, 0);
yield return null; // Один кадр анимации
}
// Этап 4: Ожидание загрузки ресурсов
ResourceRequest request = Resources.LoadAsync<Texture>("Textures/MyTexture");
yield return request;
// Этап 5: Финальная логика
Debug.Log("Последовательность завершена");
}
Ключевые особенности и лучшие практики
- Производительность: Каждая активная корутина потребляет немного памяти (примерно 1 КБ на экземпляр)
- Управление: Всегда храните ссылку на
Coroutineдля возможности остановки черезStopCoroutine() - Ошибки: Исключения в корутинах не приводят к падению всего приложения, но прерывают выполнение конкретной корутины
- Вложенность: Корутины могут запускать другие корутины через
yield return StartCoroutine(OtherRoutine())
Отличия в разных версиях Unity
В более новых версиях Unity (после 2017.3) появилась поддержка async/await паттерна, который может использоваться как альтернатива корутинам для многих асинхронных операций, особенно при работе с .NET 4.x Runtime. Однако корутины остаются предпочтительным выбором для:
- Операций, привязанных к кадрам
- Последовательностей, зависящих от времени игры
- Совместимости с Unity API, который не поддерживает async/await
Понимание всех доступных yield инструкций и их правильное применение — ключ к созданию отзывчивых, эффективных и читаемых асинхронных операций в Unity.