使用游戏引擎进行多线程处理 (Unity3D)
本文关键字:多线程处理 Unity3D 游戏 引擎 | 更新日期: 2023-09-27 17:56:10
我正在使用Unity3D和Mono制作多人在线游戏。语言是 C# 脚本。我知道 Unity 不是线程安全的。Mono 中的 C# 允许您使用 System.Threading 创建新线程。但 Unity 将禁止新线程修改任何游戏对象。
在我的代码中,我启动了一个新线程来等待来自我的一些本机 C 代码(作为插件合并到 Unity 中)的回调。这样,当调用回调时,它将位于新线程上,而不是有权操作游戏对象的 Unity 主线程上。但是,我希望修改游戏对象。我该怎么办?我应该使用主线程轮询新线程吗?还是有更好的解决方案?
有多种方法可以向主线程发出信号,表明数据在第二个线程上可用。一般来说,第一种方法可能是让第一个线程"阻塞"(等待)直到第二个线程"信号";但是,这里不赘述,这不是您想要采用的方法,因为在第二个线程上执行冗长计算时阻塞主线程会使您的游戏在最坏的情况下无响应或充其量是抖动。
因此,这留下了您提出的另一种方法:轮询。无论您觉得有必要(每帧一次,每 60 帧一次),您的主线程代码(例如在 MonoBehavior 中)都会想要检查第二个线程中任务的状态。这可以通过调用方法或检查第二个线程"拥有"的对象上的布尔值。通过这种方法,您的任务将向主线程轮询指示事情是"完成"还是"未完成"。Unity 协程可能是从主线程实现轮询逻辑的有用机制。
但是,您不一定完成。如果第二个线程要重复生成新数据到同一个变量或缓冲区中,您还必须确保主线程不会同时从第二个线程写入的缓冲区读取。对于少量数据,您可以在新数据准备就绪时使用双缓冲方法(两个缓冲区/变量,一个用于读取,一个用于写入,通过指针/引用交换交换);或者可以使用 C# 锁(但这可能会因前面所述的副作用而阻塞主线程)。
一旦您的主线程获得了所需的数据,您当然可以继续从主线程修改您的游戏对象。
请注意,您的问题并非特定于 Unity。大多数 UI 框架都有此限制(有充分的理由),线程之间的通信在每个实例中都以类似的方式解决。