После нескольких перезапусков уровня счёт скачет, а лог полон обращений к уничтоженным объектам
Глобальные игровые события объявлены статически:
public static class GameEvents
{
public static event Action<int> EnemyKilled;
public static void RaiseEnemyKilled(int reward) => EnemyKilled?.Invoke(reward);
}
public class ScoreView : MonoBehaviour
{
[SerializeField] private TMP_Text label;
void OnEnable() { GameEvents.EnemyKilled += OnEnemyKilled; }
void OnEnemyKilled(int reward)
{
_score += reward;
label.text = _score.ToString();
}
}
При первом прохождении уровня всё в порядке. После нескольких перезапусков уровня из меню счёт за одного убитого врага прибавляется несколько раз, а в логе растёт число обращений к уничтоженным объектам. Что происходит?
- Статическое событие хранит ссылки на всех прежних подписчиков: без парной отписки обработчики накапливаются и работают на мёртвых экранах
- Статические события очищаются при загрузке новой сцены, поэтому подписки тут ни при чём: дело в порядке загрузки сцен и в том, что уровень грузится поверх меню
- Нужно заменить event на обычное поле-делегат: присваивание в OnEnable перезапишет старый обработчик, и на событие всегда будет подписан ровно один экран
- Сборщик мусора уберёт уничтоженные объекты вместе с подписками: достаточно запускать сборку при выходе с уровня
