motkot
@motkot
Программирование C#.

Как вызывать ивент, когда все уже подписались?

Есть класс CharacterStats со статистикой Персонажа:

[System.Serializable]
public class CharacterStats
{
    public float MaxHealth;
    public float Health;
    public int Coins;
}

Есть класс CharacterStatsInteractor, который обрабатывает действия с репозиторием:

public class CharacterStatsInteractor
{
    private CharacterStats _characterStats;

    public int Coins => _characterStats.Coins;

    public delegate void OnCoinsValue();
    public event OnCoinsValue OnCoinsValueChanged;

    public CharacterStatsInteractor(CharacterStats repository)
    {
        _characterStats = repository;

        OnCoinsValueChanged?.Invoke();
    }

    public void AddCoins(int value)
    {
        _characterStats.Coins += value;

        OnCoinsValueChanged?.Invoke();
    }

    public void SpentCoins(int value)
    {
        _characterStats.Coins -= value;

        OnCoinsValueChanged?.Invoke();
    }

    public void TakeDamage(int value)
    {
        _characterStats.Health -= 0;
    }
}

Потом подписался на ивент:

private void OnEnable()
    {
        _player.StatsInteractor.OnCoinsValueChanged += RenderText;
    }

    private void OnDisable()
    {
        _player.StatsInteractor.OnCoinsValueChanged -= RenderText;
    }

Потом создал персонажа и написал это:

public CharacterStats CharacterStats;
    public CharacterStatsInteractor StatsInteractor;

    private void Awake()
    {
        StatsInteractor = new CharacterStatsInteractor(CharacterStats);
    }

Вроде все нормально, но ивент не срабатывает.
Я понимаю, что он не срабатывает из-за того, что вызывается ивент раньше, чем подписывается.

Надеюсь никто не напишет, что нужно просто изменить Awake на Start, так как с самого начала скрипт персонажа отключен.
  • Вопрос задан
  • 54 просмотра
Пригласить эксперта
Ответы на вопрос 2
freeExec
@freeExec
Участник OpenStreetMap
У вас сама логика кривая.
- вызвать событие в конструкторе
- получить ссылку на новый созданный объект
- подписаться на событие
- ??? где тут профит?

Вызовите просто RenderText после подписки и не мучайтесь.
Ответ написан
@zukrac
1) Либо штатно ждать следующего срабатывания. Монетки ведь обновятся ещё раз?
2) Либо самому организовать этот момент, глобальное событие "tha_gama_is_started" и по нему триггерить OnCoinsValueChanged
3) Либо сделать чтобы запись на событие была доступна до создания самого объекта (если это уместно)
например, через статическую переменную
public static event OnCoinsValue OnCoinsValueChanged;

4) Либо сделать объект менеджер событий, чтобы он был синглтон/статический, чтобы он создавался автоматически при попытке записаться на событие. И каждый сам себя подписывал в своих OnEnable
EventManager::addListener("coin_changed", RenderText);
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы