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

Что такое событие?

1.0 Junior🔥 291 комментариев
#C# и ООП

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

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

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

Что такое событие (Event) в контексте разработки на Unity?

В разработке на Unity (и в программировании в целом) событие — это механизм коммуникации между различными частями программы, который позволяет одному компоненту (издателю) уведомлять другие компоненты (подписчиков) о том, что произошло некое важное действие или изменение состояния, без необходимости жесткой связи между ними. Это реализация шаблона Наблюдатель (Observer).

Основная идея и архитектура

Система событий строится на принципе подписки (subscribe) и публикации (publish):

  • Издатель (Publisher): объявляет событие. Он "знает", когда что-то произошло (например, игрок нажал кнопку), но не знает и не должен знать, какие объекты отреагируют.
  • Подписчик (Subscriber): регистрирует свой метод-обработчик на это событие. Он "знает", как реагировать на изменение, но не управляет моментом вызова.

Реализация событий в C# и Unity

В C# события реализуются с помощью ключевого слова event и делегатов (delegate). Стандартный подход использует обобщенный делегат Action (для событий без возвращаемого значения) или EventHandler.

Пример базового события:

// Издатель
public class PlayerHealth : MonoBehaviour
{
    // 1. Объявление события. Используется Action, так как нет необходимости в специальных аргументах.
    public event Action OnPlayerDied;

    private int health = 100;

    public void TakeDamage(int damage)
    {
        health -= damage;
        if (health <= 0)
        {
            Die();
        }
    }

    private void Die()
    {
        // 2. Вызов (публикация) события. Проверка на null обязательна!
        OnPlayerDied?.Invoke();
    }
}

// Подписчик
public class GameManager : MonoBehaviour
{
    [SerializeField] private PlayerHealth playerHealth;

    private void OnEnable()
    {
        // 3. Подписка на событие в момент активации объекта.
        playerHealth.OnPlayerDied += HandlePlayerDeath;
    }

    private void OnDisable()
    {
        // 4. ОТПИСКА - КРИТИЧЕСКИ ВАЖНЫЙ МОМЕНТ во избежание утечек памяти.
        playerHealth.OnPlayerDied -= HandlePlayerDeath;
    }

    // 5. Метод-обработчик (должен соответствовать сигнатуре делегата Action)
    private void HandlePlayerDeath()
    {
        Debug.Log("Игрок погиб! Запускаем экран Game Over...");
        Time.timeScale = 0f;
    }
}

UnityEvents — встроенная система событий

Unity предоставляет собственную, сериализуемую систему событий UnityEvent, которая интегрируется с редактором.

Ключевые особенности:

  • Сериализуемы: Их настройка видна в Inspector.
  • Визуальная настройка: Позволяет связывать методы из любых компонентов на одном GameObject или публичных методов из других объектов, перетаскивая их в Inspector, без написания кода для подписки. Это основа для UI-системы (например, Button.onClick).
  • Менее производительны, чем обычные C# события, но удобны для дизайнеров и простых связей.

Пример использования UnityEvent:

public class EventEmitter : MonoBehaviour
{
    // Объявление UnityEvent с одним строковым аргументом.
    public UnityEvent<string> OnMessageReceived;

    void Start()
    {
        // Вызов события из кода
        OnMessageReceived?.Invoke("Старт игры!");
    }
}

Далее в Inspector к OnMessageReceived можно добавить "вызов" (Runtime Only) и визуально выбрать целевой GameObject и метод, например, Debug.Log(string).

Преимущества использования событий

  • Слабосвязанная архитектура: Компоненты не хранят прямые ссылки друг на друга. PlayerHealth не знает о существовании GameManager, UIManager или AchievementSystem. Это упрощает рефакторинг и добавление новой функциональности.
  • Масштабируемость: На одно событие может подписаться любое количество слушателей. Умер игрок — и GameManager, и система звука, и система частиц, и система статистики получат уведомление одним вызовом.
  • Чистота кода: Логика реакции отделена от логики инициирования действия.
  • Гибкость: В UnityEvents это позволяет дизайнерам уровней настраивать логику взаимодействий без вмешательства программиста.

Важные практические аспекты

  1. Обязательная отписка: В OnDisable или OnDestroy нужно отписываться от всех событий, особенно если подписчик имеет меньший жизненный цикл, чем издатель. Иначе издатель будет хранить ссылку на "мертвый" объект, что приведет к ошибкам и утечкам памяти.
  2. Проверка на null: Всегда используйте ?.Invoke() или проверяйте if(OnEvent != null), чтобы избежать NullReferenceException, если на событие никто не подписан.
  3. Именование: Принято начинать название события с префикса On (OnDied, OnCollected).
  4. Выбор между C# event и UnityEvent: Используйте C# события для высокопроизводительной, частой коммуникации внутри кода. Используйте UnityEvents для настройки разовых или сценарийных взаимодействий через редактор или для публичных API компонентов, где нужна интеграция с Inspector.

Таким образом, события — это фундаментальный инструмент для создания модульной, поддерживаемой и реактивной архитектуры игры в Unity, который декларирует принцип "сообщай, не спрашивай" (tell, don't ask).