【问题标题】:Multithreading with Game Engines (Unity3D)?游戏引擎的多线程(Unity3D)?
【发布时间】:2013-01-28 01:28:47
【问题描述】:

我正在使用 Unity3D 和 Mono 制作多人在线游戏。语言是 C# 脚本。我知道 Unity 不是线程安全的。 Mono 中的 C# 允许您使用 System.Threading 创建新线程。但是 Unity 会禁止新线程修改任何 GameObjects

在我的代码中,我启动了一个新线程来等待来自我的一些本机 C 代码(以 Plugins 合并到 Unity 中)的回调。这样,当回调被调用时,它将在新线程上,而不是 Unity 有权操作 GameObjects 的主线程。但是,我想要修改游戏对象。我该怎么办?我应该使用主线程来轮询新线程吗?或者有没有更好的解决方案?

【问题讨论】:

    标签: c# multithreading unity3d game-engine


    【解决方案1】:

    有不止一种方法可以向主线程发出第二个线程上可用数据的信号。一般来说,第一种方法可能是让第一个线程“阻塞”(等待)直到第二个线程“发出信号”;但是,这里不详细介绍,这不是您想要采用的方法,因为在您对第二个线程执行冗长的计算时阻塞主线程会使您的游戏在最坏的情况下无响应或在最好的情况下变得紧张。

    所以这留下了您提出的另一种方法:轮询。无论您经常觉得有必要(每帧一次,每 60 帧一次),您的主线程代码(例如在 MonoBehaviour 中)都会想要检查第二个线程中任务的状态。这可以通过调用方法或检查第二个线程“拥有”的对象上的布尔值来实现。通过这种方法,您的任务将指示主线程轮询事情是“完成”还是“未完成”。 Unity 协程可能是一种有用的机制,可用于从主线程实现轮询逻辑。

    但是,您还不一定完成。如果您的第二个线程将重复生成新数据到同一个变量或缓冲区中,您还必须确保您的主线程不会同时从您的第二个线程正在写入的缓冲区中读取。对于少量数据,当新数据准备好时,您可以使用双缓冲方法(两个缓冲区/变量,一个用于读取,一个用于写入,通过指针/引用交换进行交换);或者您可以使用 C# 锁(但这可能会阻塞您的主线程并产生前面描述的副作用)。

    一旦您的主线程获得所需的数据,您当然可以继续从主线程修改您的游戏对象。

    请注意,您的问题并非针对 Unity。大多数 UI 框架都有这个限制(有充分的理由),并且线程之间的通信在每个实例中都以类似的方式解决。

    【讨论】:

    • 谢谢!确实。我将实施投票,是的,我同意这个问题在某种程度上是持久的。
    猜你喜欢
    • 1970-01-01
    • 2015-12-06
    • 2014-08-27
    • 2011-07-07
    • 2017-03-31
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 2020-01-17
    相关资源
    最近更新 更多