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

В чем разница между delegates, C# events, UnityEvent и EventSystem?

2.0 Middle🔥 151 комментариев
#C# и ООП

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

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

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

Различия между Delegates, C# Events, UnityEvent и EventSystem

Эти понятия образуют иерархию абстракций для реализации паттерна observer (наблюдатель) в Unity, от низкоуровневых языковых возможностей C# до высокоуровневых систем движка.

Delegates (Делегаты)

Делегат — это типобезопасный указатель на метод в C#, основа для всех остальных механизмов событий. Это низкоуровневая конструкция языка.

// 1. Объявление типа делегата
public delegate void DamageHandler(float damageAmount, string damageType);

// 2. Создание экземпляра делегата
DamageHandler onDamageTaken;

// 3. Подписка методов
void Start() {
    onDamageTaken += PlayerTookDamage;
    onDamageTaken += UpdateUI;
}

// 4. Вызов всех подписанных методов
void ApplyDamage(float damage) {
    onDamageTaken?.Invoke(damage, "physical");
}

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

  • Языковая конструкция C#, а не Unity
  • Позволяет хранить и вызывать список методов
  • Отсутствует встроенная защита от несанкционированного вызова (подписчики могут вызывать делегат)
  • Нет поддержки в инспекторе Unity

C# Events (События C#)

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

public class Health : MonoBehaviour {
    // Объявление события на основе делегата
    public event Action<float> OnHealthChanged;
    
    private float currentHealth;
    
    public void TakeDamage(float damage) {
        currentHealth -= damage;
        // Вызывать событие могут только методы этого класса
        OnHealthChanged?.Invoke(currentHealth);
    }
}

// В другом классе - только подписка/отписка
public class HealthBar : MonoBehaviour {
    void Start() {
        healthComponent.OnHealthChanged += UpdateHealthDisplay;
    }
    
    void UpdateHealthDisplay(float newHealth) {
        // Обновляем UI
    }
}

Ключевые различия от делегатов:

  • Инкапсуляция: внешние классы могут только подписываться (+=) и отписываться (-=)
  • Внешний код не может вызвать событие, очистить все подписки (= null) или получить список подписчиков
  • Повышает безопасность архитектуры
  • По-прежнему не отображается в инспекторе Unity

UnityEvent

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

using UnityEngine;
using UnityEngine.Events;

public class GameEventTrigger : MonoBehaviour {
    // Объявление UnityEvent с кастомными параметрами
    [System.Serializable]
    public class DamageEvent : UnityEvent<float, GameObject> {}
    
    // Событие, отображаемое в инспекторе
    public DamageEvent onDamageReceived;
    
    // UnityEvent без параметров
    public UnityEvent onPlayerDeath;
    
    void Start() {
        // Можно подписываться и через код
        onDamageReceived.AddListener(HandleDamage);
    }
    
    void ApplyDamage(float damage, GameObject source) {
        onDamageReceived.Invoke(damage, source);
    }
}

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

  • Отображается в инспекторе Unity — можно настраивать визуально без написания кода
  • Поддерживает сериализацию (сохранение между сессиями редактора)
  • Позволяет дизайнерам/художникам настраивать логику без программирования
  • Производительность: медленнее, чем чистые C# events из-за проверок и оберток
  • Поддерживает постоянные (Persistent) и динамические (Runtime) вызовы

EventSystem (Система событий UI)

Это полноценная система Unity для обработки взаимодействий с пользовательским интерфейсом. Работает поверх UnityEvent, но служит другой цели.

// EventSystem используется неявно через компоненты UI
public class ButtonEventHandler : MonoBehaviour, IPointerClickHandler {
    // Реализация интерфейса обработки событий UI
    public void OnPointerClick(PointerEventData eventData) {
        Debug.Log($"Клик по {gameObject.name} в позиции {eventData.position}");
    }
}

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

  • Специализированная система для UI событий (клики, наведение, перетаскивание)
  • Основана на Raycasting для определения цели события
  • Использует Input Modules (StandaloneInputModule, TouchInputModule)
  • Иерархическая обработка событий через интерфейсы (IPointerClickHandler и др.)
  • Работает с Graphic Raycaster и Physics Raycaster

Сравнительная таблица

КритерийDelegatesC# EventsUnityEventEventSystem
УровеньЯзык C#Язык C#Класс UnityСистема Unity
ИнспекторНетНетДаДа (для UI компонентов)
БезопасностьНизкаяВысокаяВысокаяВысокая
ПроизводительностьВысокаяВысокаяСредняяЗависит от сложности UI
ИспользованиеЛюбые вызовыАрхитектура кодаГибкое, с редакторомТолько UI события
СериализацияНетНетДаЧастично

Рекомендации по выбору

  1. Delegates — для внутренней логики класса, где не нужна инкапсуляция
  2. C# Events — для коммуникации между компонентами в коде, когда не требуется настройка в инспекторе
  3. UnityEvent — когда нужна настройка в редакторе или не-programmer friendly дизайн
  4. EventSystem — исключительно для обработки взаимодействий с пользовательским интерфейсом

Архитектурный совет: Используйте C# events для высокочастотных игровых событий (здоровье, передвижение) и UnityEvent для редких, настраиваемых событий (активация ловушек, катсцены), чтобы сбалансировать производительность и гибкость.