← Назад к вопросам

Можно ли написать пользовательскую yield инструкцию?

1.0 Junior🔥 141 комментариев
#C# и ООП#Другое

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Можно ли написать пользовательскую yield инструкцию в C# и Unity?

Да, в C# и, соответственно, в Unity можно создавать пользовательские yield инструкции. Однако важно понимать, что ключевое слово yield само по себе является частью языка C# и используется в методах-генераторах (методах, возвращающих IEnumerator или IEnumerable). Вы не можете создать новое ключевое слово или изменить поведение самого yield.

Что вы можете сделать — это создать собственные типы условий ожидания (yield instructions), которые будут возвращаться из метода-генератора и управлять его выполнением. В контексте Unity это особенно полезно для создания сложных, кастомных паттернов ожидания в корутинах.

Как это работает в Unity

В Unity корутины основаны на интерфейсе IEnumerator. Когда вы используете yield return, вы возвращаете объект, который указывает движку, когда следует продолжить выполнение метода. Unity предоставляет ряд стандартных объектов для этого (например, WaitForSeconds, WaitForFixedUpdate, WaitForEndOfFrame).

Вы можете создать свой собственный класс, который будет выступать такой инструкцией. Для этого ваш класс должен быть просто объектом, который корутина возвращает через yield return. Движок Unity будет проверять определенные условия, чтобы понять, когда продолжить выполнение. Однако для реализации полноценного "ожидания" с проверкой условия на каждом фрейме, чаще используется другой подход.

Пример создания простой пользовательской yield инструкции

Самый простой способ — создать класс, который корутина будет возвращать. Но такой объект сам по себе не будет управлять ожиданием. Для создания инструкции, которая действительно "ждет" выполнения определенного условия, нужно реализовать интерфейс IEnumerator в вашем классе или использовать CustomYieldInstruction.

Использование CustomYieldInstruction (современный подход)

Unity предоставляет базовый класс CustomYieldInstruction. Начиная с версии Unity 5.3, он является рекомендуемым способом создания пользовательских yield инструкций. Вам нужно отнаследоваться от него и переопределить свойство keepWaiting.

using UnityEngine;
using System.Collections;

public class WaitUntilCondition : CustomYieldInstruction
{
    // Делегат для условия, которое мы проверяем
    private System.Func<bool> condition;

    // Конструктор принимает условие (делегат)
    public WaitUntilCondition(System.Func<bool> conditionToWaitFor)
    {
        this.condition = conditionToWaitFor;
    }

    // Свойство keepWaiting проверяется движком каждый фрейм.
    // Корутина продолжит выполнение только когда оно вернет false.
    public override bool keepWaiting
    {
        get
        {
            // Ждем, пока условие не станет истинным.
            // Возвращаем true, если условие ЛОЖНО (т.е. еще нужно ждать).
            // Возвращаем false, если условие ИСТИННО (можно продолжать).
            return !condition();
        }
    }
}

Использование в корутине:

IEnumerator MyCustomCoroutine()
{
    Debug.Log("Ожидание выполнения условия...");
    
    // Создаем кастомную инструкцию, которая ждет, пока переменная isReady станет true
    yield return new WaitUntilCondition(() => isReady);
    
    Debug.Log("Условие выполнено! Продолжаем.");
}

Альтернативный подход: реализация IEnumerator (классический)

Вы также можете создать класс, который сам реализует IEnumerator. Это более сложный, но гибкий метод.

public class CustomWaitOperation : IEnumerator
{
    private System.Func<bool> condition;

    public CustomWaitOperation(System.Func<bool> condition)
    {
        this.condition = condition;
    }

    // Current обычно возвращает null или сам объект.
    public object Current => null;

    // MoveNext() вызывается движком. Возвращает true, если нужно продолжать ожидание.
    public bool MoveNext()
    {
        // Ждем, пока условие не станет истинным.
        // Возвращаем true, если условие ЛОЖНО (ждем дальше).
        return !condition();
    }

    public void Reset() { }
}

Использование:

IEnumerator MyCoroutine()
{
    yield return new CustomWaitOperation(() => player.IsAlive);
}

Практические примеры использования в Unity

Кастомные yield инструкции крайне полезны для:

  • Ожидания специфических игровых событий: WaitUntilEnemyDestroyed, WaitForDialogComplete.
  • Создания сложных последовательностей: WaitForParallelTasks (ожидание нескольких асинхронных операций).
  • Интеграции с внешними системами: WaitForWebResponse, WaitForAssetBundleLoad.
// Пример: ожидание, пока здоровье игрока опустится ниже порога
public class WaitUntilHealthLow : CustomYieldInstruction
{
    private Player player;
    private float threshold;

    public WaitUntilHealthLow(Player player, float threshold)
    {
        this.player = player;
        this.threshold = threshold;
    }

    public override bool keepWaiting => player.CurrentHealth > threshold;
}

Ключевые выводы

  1. Да, можно создать пользовательскую yield инструкцию в Unity, но не как новое ключевое слово языка, а как объект, управляющий ожиданием в корутине.
  2. Основной механизм — использование базового класса CustomYieldInstruction и переопределение свойства keepWaiting. Это самый чистый и поддерживаемый способ.
  3. Кастомные инструкции значительно повышают читаемость и управляемость корутин, позволяя инкапсулировать сложные условия ожидания в отдельные классы.
  4. Производительность: Помните, что свойство keepWaiting или метод MoveNext() будут вызываться движком каждый фрейм (или в момент проверки), поэтому условие внутри них должно быть легковесным.

Таким образом, создание пользовательских yield инструкций — это мощный инструмент в арсенале Unity разработчика для написания чистого, модульного и легко читаемого асинхронного кода с использованием корутин.