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

Используешь ли Event C# в работе

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

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

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

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

Использование C# Events в разработке на Unity

Да, я активно использую механизм C# events (событий) в своей работе на Unity. Это не просто предпочтение, а ключевой инструмент для создания декларативного, связанного (coupling) и поддерживаемого кода, особенно в контексте игрового цикла, пользовательского интерфейса и систем взаимодействия объектов. События представляют собой реализацию шаблона Observer (Наблюдатель), который идеально ложится на парадигму "состояние-изменение-реакция", столь частую в играх.

Ключевые преимущества и сценарии использования

  • Снижение связанности (Loose Coupling): Издатель события не знает и не зависит от подписчиков. Это позволяет легко добавлять новую реакцию на событие (например, проигрывание звука, обновление UI, логирование) без изменения исходного класса-источника.
  • Реактивность и отзывчивость: События идеальны для мгновенной реакции на изменения в игре: смерть персонажа, подбор предмета, нажатие кнопки.
  • Управление состоянием UI: UnityEvent (частный случай C# event, сериализуемый в Inspector) — основа для связи игровой логики и UI через Inspector без написания явных ссылок в коде.
  • Архитектура и коммуникация между системами: События — краеугольный камень более сложных архитектурных решений, таких как шина событий (Event Bus) или менеджер событий, для глобальной коммуникации.

Практические примеры из проектов

1. Простой C# event для игровой механики:

public class PlayerHealth : MonoBehaviour
{
    public event System.Action OnPlayerDeath; // Объявление события
    public event System.Action<int> OnHealthChanged;

    private int _currentHealth = 100;

    public void TakeDamage(int damage)
    {
        _currentHealth -= damage;
        OnHealthChanged?.Invoke(_currentHealth); // Вызов события

        if (_currentHealth <= 0)
        {
            Die();
        }
    }

    private void Die()
    {
        OnPlayerDeath?.Invoke(); // Безопасный вызов (проверка на null)
        // Другая логика смерти...
    }
}

// Где-то в другом классе (UI, система достижений, звук)
public class GameUI : MonoBehaviour
{
    [SerializeField] private PlayerHealth _playerHealth;
    [SerializeField] private Text _healthText;

    private void OnEnable()
    {
        _playerHealth.OnHealthChanged += UpdateHealthUI; // Подписка
        _playerHealth.OnPlayerDeath += ShowGameOverScreen;
    }

    private void OnDisable()
    {
        // ВАЖНО: отписываемся для избежания утечек памяти!
        _playerHealth.OnHealthChanged -= UpdateHealthUI;
        _playerHealth.OnPlayerDeath -= ShowGameOverScreen;
    }

    private void UpdateHealthUI(int newHealth)
    {
        _healthText.text = $"Health: {newHealth}";
    }

    private void ShowGameOverScreen()
    {
        // Логика показа экрана "Game Over"
    }
}

2. Использование UnityEvent для настройки в Inspector:

public class InteractableObject : MonoBehaviour
{
    // Это событие можно настраивать визуально в окне Inspector,
    // перетаскивая методы из любых компонентов на этом или других GameObject.
    public UnityEvent OnInteracted;

    public void Interact()
    {
        Debug.Log("Object interacted!");
        OnInteracted?.Invoke(); // Вызов UnityEvent
    }
}

В Inspector к OnInteracted можно добавить вызов метода, например, AudioSource.Play(), Animator.SetTrigger() или активацию другого объекта, что делает прототипирование и дизайнерскую настройку невероятно быстрыми.

Важные нюансы и лучшие практики

  • Отписка (Unsubscribing): Критически важно отписываться от событий при уничтожении объекта (OnDisable, OnDestroy), особенно если издатель живет дольше подписчика. Иначе это приводит к утечкам памяти (ссылка на "мертвый" объект сохраняется) и возможным ошибкам.
  • Потокобезопасность (Thread Safety): В Unity основной поток исполнения — один, поэтому эта проблема менее актуальна, но в целом вызов ?.Invoke() является потокобезопасным способом.
  • Именование: Я следую соглашению: префикс On для событий (OnDied, OnScoreChanged).
  • Производительность: Для высокочастотных событий (например, Update) стоит избегать их использования в пользу прямых вызовов или других шаблонов (например, Dependency Injection через интерфейсы), чтобы не тратить ресурсы на управление списком делегатов.

Вывод: C# events и UnityEvent — это не взаимозаменяемые, а дополняющие друг друга инструменты. C# events — для строгой, типобезопасной связи внутри кода. UnityEvent — для гибкой, настраиваемой дизайнерами связи через редактор. Их грамотное комбинирование является признаком качественной архитектуры Unity-проекта, позволяя создавать расширяемые, модульные и удобные в поддержке системы.

Используешь ли Event C# в работе | PrepBro