Ras*_*ond 4 c# unity-game-engine
在 Unity 中,我有一个脚本,我在其中通过 TCP 连接到套接字,并希望在每一帧都使用此连接。之后我需要处理和清理。我的想法是用来Start()开始连接和OnDestroy()
public class Foo : MonoBehaviour
{
void Start()
{
// start TCP connection
}
void Update()
{
// use connection
}
void OnDestroy()
{
// cleanup
}
}
Run Code Online (Sandbox Code Playgroud)
我需要清理来执行任何发生的事情。OnDestroy()无论对象发生什么情况,该方法是否保证在应用程序停止之前(在独立模式和编辑器中)被调用?如果没有,我如何保证清理?
不它不是!
OnApplicationQuit当您的应用程序因某种原因崩溃时,甚至可能不会被调用。
还有其他特定情况,两者都没有被调用。我知道,根据我自己的经验,例如在 HoloLens2 上的应用程序并未关闭,而只是处于休眠状态。如果您然后通过 HoloLens 主“菜单”关闭它们,那么您实际上是通过任务管理器杀死它们。
这是非常脏,原因既不OnDestroy也不OnApplicationQuit或任何其他特定的统一消息被调用,我们结束了佐比线程和依然占据TCP端口。
如果你真的想确定(例如为了免费连接,杀死线程等)我最终做的是用解构器(Finalizer)创建一个专用类
解构器是纯 c# 并且不依赖于 Unity 的正确关闭,因此即使垃圾收集器自动完成其工作后应用程序因崩溃而终止,也能保证调用它。
public class Foo : MonoBehaviour
{
private class FooInternal
{
public FooInternal()
{
// create TCP connection
// start thread etc
}
public void Update ()
{
// e.g. forward the Update call in order to handle received messages
// in the Unity main thread
}
public ~FooInternal()
{
// terminate thread, connection etc
}
}
private FooInternal _internal;
void Start()
{
_internal = new FooInternal ();
}
void Update()
{
_internal.Update();
}
}
Run Code Online (Sandbox Code Playgroud)
如果你从不传递对_internal其他任何东西的引用,GC 也应该在这个实例被销毁后自动终止它。
你正在寻找OnEnable建立你的联系,并OnDisable清理它。
OnDestroy(和fwiw)的问题OnApplicationQuit是,如果禁用脚本,则不会调用它,如果出现以下情况,则可能会发生这种情况:
SetActive(false)其GameObject父母或任何其父母。enabled = false在脚本组件上设置。GameObject通过取消选中检查器中的框来在播放模式下禁用该或其任何父级。问题是,如果脚本在禁用后重新Start启用,则不会调用它(它将第一次调用,但不会再调用),这在与上述列表相反的所有情况下都会发生(如以及当编辑器在播放模式下完成脚本重新编译时)。
另一方面:
OnDisable当脚本由于上述任何原因转换为禁用状态时,以及OnDestroy所有涉及的内容时,将被调用OnApplicationQuit。OnEnable当脚本由于上述任何原因以及涵盖的所有内容而转换为启用状态时,将被调用Start。此外,您还将获得 Unity 的 1:1 对应OnEnable和OnDisable调用(当然您可以随时自己调用它们)。
您几乎Start只会有和的 1:1 对应关系OnDestroy:值得注意的例外是,如果脚本组件最初被禁用(即您在编辑模式下禁用了它),但它GameObject已启用,您仍然会OnDestroy在脚本上被调用,即使Start是没有被调用(现在我想这可能是一个错误)。另外,当然,您会错过上述所有情况。
OnEnable+OnDisable然而,干净地处理所有这些,并且通常以简单的方式完全按照您希望的方式进行操作,(理论上)没有奇怪的怪癖或陷阱。
对于问题本身,是的,OnDestroy是可靠的:当脚本被销毁时,它会按照记录被调用。
当然,如果应用程序崩溃,它不会被调用,但一般来说,您会遇到更大的问题,而这不是您通常编写代码的情况。如果你在运行游戏的机器旁边引爆手榴弹,它也可能不会被调用,但是,同样,这都属于“未定义行为”领域。
| 归档时间: |
|
| 查看次数: |
679 次 |
| 最近记录: |