简体   繁体   English

在MonoBehaviour中注销事件处理程序

[英]Unregister event handler in MonoBehaviour

I register an event handler (delegate) in the Start method within a class inherited from MonoBehaviour . 我在从MonoBehaviour继承的类中的Start方法中注册了一个事件处理程序(委托)。 I want to prevent memory leaks in this case. 我想在这种情况下防止内存泄漏。

public class CharactersController: MonoBehaviour
{
    void Start()
    {
        npc.CollisionEntered += OnNpcCollisionEnter;
    }
}

What is correct or the best method to unregister the delegate? 什么是注销委托的正确或最佳方法? There is a method OnDestroy http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnDestroy.html 有一种方法OnDestroy http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnDestroy.html

The doc says that 医生说

This function is called when the MonoBehaviour will be destroyed. 当MonoBehaviour被销毁时,将调用此函数。

OnDestroy will only be called on game objects that have previously been active. 仅在以前处于活动状态的游戏对象上调用OnDestroy。

But it's not clear when MonoBehaviour will be destroyed and what if a gameobject hasn't been activated previously. 但是尚不清楚何时会破坏MonoBehaviour,以及如果先前未激活游戏对象会怎样。

OnEnable中注册事件,然后在OnDisable中注销事件是适当的。

Start() method will not get called unless the behavior is enabled . 除非启用了行为,否则不会调用Start()方法 And it can only be enabled if the game object that it's on is activated. 而且只有在其所在的游戏对象被激活时才能启用。 So, you can safely assume that if the behavior gets OnDestroy() called, it did get a call to Start() earlier. 因此,您可以放心地假设,如果该行为被调用了OnDestroy() ,则它确实早先获得了对Start()的调用。

The destruction of mono behaviour happens within the same frame (before rendering) . 单声道行为的破坏发生在同一帧内(渲染之前) However, if you are not just asking this because of precaution for memory leaks, but your logic depends on that, something is definitely wrong with it. 但是,如果您不只是因为预防内存泄漏而问这个问题,而是您的逻辑依赖于此,那肯定是有问题的。

As @Programmer correctly noted, your code, most likely, should subscribe and unsubscribe to events in OnEnabled and OnDisabled instead. 正如@Programmer正确指出的那样,您的代码很可能应该订阅和取消订阅OnEnabledOnDisabled事件。 This follows the concept of component design pattern much better: after all, this pattern assumes (and quite logically so) that components only do their work when deliberately activated by outside systems, and go back to sleep when deactivated. 这更好地遵循了组件设计模式的概念:毕竟,该模式假设(并且在逻辑上如此)假定组件仅在由外部系统故意激活时才起作用,而在禁用时才返回睡眠状态。 Now, Unity developers have to bend these guidelines a little in a lot of places, because MonoBehaviours are almost the only point of entry they have in terms of C# code, but still, it's better to follow the implicit rules of the system. 现在,Unity开发人员不得不在很多地方略微修改这些准则,因为在C#代码方面,MonoBehaviours几乎是他们拥有的唯一切入点,但是仍然最好遵循系统的隐式规则。

And finally, I honestly never saw considerable performance problems in a Unity project because of memory leaks. 最后,老实说,由于内存泄漏,我从未在Unity项目中看到过明显的性能问题。 It is a good that you thinking about it, but your time would be considerably better spent if you eliminated instantiation and destruction of the objects altogether, by moving them to use an object pool , as they are much more often tend to be a source of problems. 考虑一下这是件好事,但是如果通过将对象移动到对象池中而完全消除了对象的实例化和销毁,则可以花费更多的时间,因为它们经常是对象的来源。问题。

If you are only registering the one handler on Start and your CharactersController lasts the lifetime of the application then you aren't going to be leaking memory. 如果您仅在Start上注册一个处理程序,并且CharactersController可以延长应用程序的生命周期,那么您就不会泄漏内存。 It would be more likely to leak if you were registering the handler at some recurring event in the object's lifetime, and then not unregistering it later. 如果您在对象生存期内的某个重复发生的事件中注册处理程序,然后又不注销它,则泄漏的可能性更大。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM