我有一个小型事件处理程序,它在 Start 方法中订阅来自不同对象的许多事件,还有一个 OnDestroy 方法,它取消订阅脚本在 Start 方法中订阅的所有事件。
private void Start()
{
_winPanelController.OnGiveAwards += CalculateCoins;
_revivePaymentManager.OnUpdatedBalance += SaveBalanceToJSON;
_revivePaymentManager.OnPayingFinished += RespawnAllEnemies;
_revivePaymentManager.OnPayingFinished += RevivePlayer;
_revivePaymentManager.OnPayingNotFinished += InformPlayerNotEnoughGems;
_actorUI.OnPlayerStop += SetPlayerMovement;
_wavesController.OnWin += ActivationWinPanel;
_wavesController.OnStoppedWave += StopSpawningForAllSpawners;
_wavesController.OnEnemyLevelUp += SetNewLevelForEnemies;
_player.OnDead += EnableRevivePanel;
_player.OnRevived += RespawnAllEnemies;
foreach (var spawner in _enemySpawner)
{
spawner.OnXPCollected += CalculateCollectedXP;
spawner.OnDamageCollected += CalculateCollectedDamage;
}
}
private void OnDestroy()
{
_winPanelController.OnGiveAwards -= CalculateCoins;
_revivePaymentManager.OnUpdatedBalance -= SaveBalanceToJSON;
_revivePaymentManager.OnPayingFinished -= RespawnAllEnemies;
_revivePaymentManager.OnPayingFinished -= RevivePlayer;
_revivePaymentManager.OnPayingNotFinished -= InformPlayerNotEnoughGems;
_wavesController.OnWin -= ActivationWinPanel;
_wavesController.OnStoppedWave -= StopSpawningForAllSpawners;
_wavesController.OnEnemyLevelUp -= SetNewLevelForEnemies;
_player.OnDead -= EnableRevivePanel;
_player.OnRevived -= RespawnAllEnemies;
foreach (var spawner in _enemySpawner)
{
spawner.OnXPCollected -= CalculateCollectedXP;
spawner.OnDamageCollected -= CalculateCollectedDamage;
}
}`
问题是我不明白在哪里可以跟踪我订阅了多少个事件,它们占用了多少 RAM 或 CPU 时间?或者说不可能追踪这个?如果我不取消订阅这些事件会发生什么,我如何跟踪内存泄漏?
我尝试在 Memory Profiler 中查找与事件相关的内容,但也没有找到任何内容。我在Profiler中发现最多的是进程
Update.ScriptsRunBehaviorUpdate > BehaviorUpdate > EventSystem.Update() [Invoke]
。这是 Unity 的标准 EventSystem 吗?
我不明白在哪里可以跟踪我订阅了多少活动
您可以查看this问题的答案。有一些选项可以使用附加的调试器和通过反射来完成此操作。不过,我绝不会建议您在运输构建上使用反射。如果它只是为了您和调试目的,那很好,但它会带来开销,并且可能不适用于所有平台。
它们需要多少 RAM 或 CPU 时间?
很少。它们在内部列表中保存对对象的引用和函数指针。即使您有数百名订阅者,您实际上也不会注意到影响。它基本上是一个循环,迭代所有函数以在其对象上调用它们并传递参数。
或者是不可能追踪这个吗?
请参阅上面我关于调试它们的观点。您完全可以查看内部发生的情况,但如果您真的想跟踪它,您可能应该运行一个内部事件系统,但这也可能会变得混乱。
如果我不取消订阅这些事件会发生什么,我如何跟踪内存泄漏?
这是一个非常好的问题。通常,当一个对象超出范围并被垃圾收集时,事件不会关心它,并且会将其从调用列表中删除。在 Unity 中,当您订阅 Unity 托管对象(从 MonoBehaviour 或 ScriptableObject 继承的对象)时,它们不会从调用列表中删除,并且将在它们上调用事件。我建议取消订阅它们,如果您发现某个不应该存在的对象上有一些奇怪的 NullReferenceException,请确保您已取消订阅您所描述的所有事件。