В чем разница между delegates, C# events, UnityEvent и EventSystem?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Различия между 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
Сравнительная таблица
| Критерий | Delegates | C# Events | UnityEvent | EventSystem |
|---|---|---|---|---|
| Уровень | Язык C# | Язык C# | Класс Unity | Система Unity |
| Инспектор | Нет | Нет | Да | Да (для UI компонентов) |
| Безопасность | Низкая | Высокая | Высокая | Высокая |
| Производительность | Высокая | Высокая | Средняя | Зависит от сложности UI |
| Использование | Любые вызовы | Архитектура кода | Гибкое, с редактором | Только UI события |
| Сериализация | Нет | Нет | Да | Частично |
Рекомендации по выбору
- Delegates — для внутренней логики класса, где не нужна инкапсуляция
- C# Events — для коммуникации между компонентами в коде, когда не требуется настройка в инспекторе
- UnityEvent — когда нужна настройка в редакторе или не-programmer friendly дизайн
- EventSystem — исключительно для обработки взаимодействий с пользовательским интерфейсом
Архитектурный совет: Используйте C# events для высокочастотных игровых событий (здоровье, передвижение) и UnityEvent для редких, настраиваемых событий (активация ловушек, катсцены), чтобы сбалансировать производительность и гибкость.