Bevy 0.2

2020-09-20 07:11:36

在最初的Bevy发布一个月后,感谢87位贡献者、174个拉取请求和我们慷慨的赞助商,我很高兴在crates.io!上宣布Bevy 0.2发布。

对于那些不知道的人来说,Bevy是一个令人耳目一新的简单的数据驱动的游戏引擎,它内置在Rust。您可以查看快速入门指南以开始使用。Bevy也是永远免费和开源的!您可以在GitHub上获取完整的源代码。

Bevy在整个引擎中使用多线程:ECS调度、资源加载、渲染等。在此版本之前,它几乎所有这些任务都使用人造丝。Raon很好,因为它通常很简单,只需调用ome_list.par_iter().for_each(|x|do_omething(X))即可。然后,Rayon会自动将for_each分解为多个任务,并在尽可能多的内核上运行它们。如果您想轻松地并行化代码,Rayon是一个很好的选择,但它的缺点是非常需要CPU。

Bevy(以及其他一些使用rayon的铁锈游戏引擎和ECS框架)已经收到反馈,称它们过度占用CPU/使用量与实际完成的工作量不成正比。

我们决定通过构建一个自定义的异步友好任务系统来解决这个问题,该系统支持创建特定于上下文的任务池。例如,您可能有单独的池用于计算、IO、网络等。这也为我们提供了根据工作类型和/或优先级适当平衡工作负载的灵活性。赢得的CPU使用率一直很高:

(的子集)bevy现在使用WebAssembly/WASM在Web上运行!具体地说,bevy应用程序可以运行bevy ECS时间表、响应输入事件、创建空画布(使用winit)以及其他一些功能。这是一个巨大的第一步,但重要的是要指出,仍然有一些缺失的部分,如2D/3D渲染、多线程和声音。

他们将bevy用于游戏逻辑,并通过将ASCII技术的游戏状态从该bevy系统传递到此JavaScript函数来巧妙地绕过呈现限制。

Bevy ECS查询是从实体组件系统检索数据的一种灵活方式。使用查询的系统已经并行运行,但在此更改之前,查询本身不能并行迭代。Bevy 0.2增加了轻松并行迭代查询的能力:

FN系统(池:res<;ComputeTaskPool>;,MUT查询:查询<;&;MUT转换>;){查询。ITER()。PAR_ITER(32)。FOR_EACH(&A;POOL,|MUT转换|{转换。翻译(ve3::new(1.0,0.0,0.0));});}。

这提供了一个运行在新的bevy_task系统之上的很好的功能性API(类似于Rayon)。它将查询分解为32个批,并在bevy任务系统中将每个批作为不同的任务运行。

//旧FN系统(翻译:&;平移,旋转:&;旋转,缩放:&;缩放){println!(";{}";,翻译。0,旋转。0,缩放。0);}//新的FN系统(转换:&;转换){println!(";{}";,转换。平移()、变换。旋转()、变换。Scale());}。

贝维的旧变换系统使用单独的平移、旋转和缩放组件作为真实源。用户在他们的系统中使用这些组件进行修改,之后它们被同步到LocalTransform组件,考虑到层次结构,该组件又被同步到全局转换组件。这很好,有几个原因:

检索单个组件(如翻译)的缓存效率略高(因为需要访问的数据更少)。

单个组件是真相的来源,因此LocalTransform在用户系统运行时已过时。如果需要最新的完整转换,则必须通过访问所有三个组件来手动构建。

很难讲道理。用户需要考虑5个组件,它们之间的交互方式各不相同。

将转换设置为特定的矩阵值(例如:mat4::lookat())非常麻烦,除非用户显式禁用组件同步,否则该值将立即被覆盖。

考虑到这些问题,我们决定使用单个统一的本地到父转换组件作为真值来源,并使用计算出的GlobalTransform组件进行世界空间转换。我们认为这个API会更容易使用和推理。Unity也在考虑对他们的ECS进行类似的改造,在这个紫晶论坛的主题中发生了很多关于这个话题的讨论。

多亏了gilrs库,bevy输入插件现在可以跨平台支持大多数控制器了!

Fn Button_System(GamePad:res<;Vec<;Gamepad>;,Button_Input:RES<;Input<;GamepadButton>;){表示游戏手柄中的游戏手柄。Iter(){IF BUTTON_INPUT。Just_Press(GamepadButton(*Gamepad,GamepadButtonType::RightTrigger)){println!(";按下右触发器!";);}。

我们将实体ID从随机的UUID更改为递增的世代索引。随机UUID很好,因为它们可以在任何地方创建,在游戏运行中是唯一的,并且可以安全地持久保存到文件中或跨网络重用。我真的希望我们能让它们工作,但它们最终相对于其他选择来说太慢了。随机性具有可测量的成本,并且必须使用散列图来查找实体位置。

通过转移到世代索引(我们使用HECS实现),我们可以直接使用实体ID作为数组索引,这使得实体位置查找速度非常快。

对于不会发生任何变化的查询,我实现了只读特征(";Read&34;Characterns)。这使我们可以保证查询不会改变任何东西。

这给了我们一个非常好的速度提升。我们可以安全地做到这一点,这要归功于新的只读查询和将世界突变API更改为可变的世界借入的组合。

系统中的查询尚未启用此功能,因为一个系统可能有多个查询,这些查询可能会以不会使可变访问唯一的方式同时访问。我认为那是一个可以解决的问题,但需要多做一点工作。幸运的是,for-each系统没有任何冲突风险,所以我们现在在那里使用无锁查询。

由于这些优化,直接组件查找比过去快得多:

请注意,此基准使用的是world.get::<;T>;(实体)。Query.get::<;T>;(实体)应该有类似于HECS结果的结果,因为它仍然使用锁。最终,我希望我们也能从系统查询中移除锁定。

非常感谢87位贡献者,他们使这个版本(以及相关文档)成为可能!