#bevy-plugin #random #bevy #game-engine #secure-random #chacha #gamedev

bevy_turborand

为Bevy游戏引擎启用ECS优化随机数生成的插件

15个版本 (8个破坏性更新)

0.9.0 2024年7月4日
0.8.2 2024年2月24日
0.7.0 2023年11月4日
0.6.0 2023年7月10日
0.2.0 2022年7月30日

#172 in 游戏开发

Download history 138/week @ 2024-04-26 163/week @ 2024-05-03 118/week @ 2024-05-10 105/week @ 2024-05-17 111/week @ 2024-05-24 145/week @ 2024-05-31 84/week @ 2024-06-07 89/week @ 2024-06-14 89/week @ 2024-06-21 206/week @ 2024-06-28 226/week @ 2024-07-05 76/week @ 2024-07-12 107/week @ 2024-07-19 250/week @ 2024-07-26 205/week @ 2024-08-02 72/week @ 2024-08-09

每月650次下载
3 个crate 中使用

Apache-2.0 OR MIT

47KB
591

bevy_turborand

CI License Cargo Documentation

一个为Bevy游戏引擎启用随机数生成的插件,基于turborand构建。实现了Bevy的确定性RNG RFC中的想法。

turborand的内部实现使用Wyrand,这是一个简单快速的生成器,但不是加密安全的,以及ChaCha8,这是一个加密安全的生成器,经过调整以进行8轮ChaCha算法,以提高吞吐量而不牺牲太多安全性,如Too Much Crypto论文中所述。

示例

use bevy::prelude::*;
use bevy_turborand::prelude::*;

#[derive(Debug, Component)]
struct Player;

fn setup_player(mut commands: Commands, mut global_rng: ResMut<GlobalRng>) {
    commands.spawn((
        Player,
        RngComponent::from(&mut global_rng)
    ));
}

fn do_damage(mut q_player: Query<&mut RngComponent, With<Player>>) {
    let mut rng = q_player.single_mut();

    println!("Player attacked for {} damage!", rng.u32(10..=20));
}

fn main() {
    App::new()
        .add_plugins(RngPlugin::default())
        .add_systems(Startup, setup_player)
        .add_systems(Update, do_damage)
        .run();
}

确定性RNG

为了使您的游戏/应用程序具有确定性,必须对Rng进行初始化。可以给GlobalRngRngPlugin提供一个种子,然后设置内部PRNG以表现出确定性。无需手动初始化每个RngComponent,只要初始化了GlobalRng,就可以直接从全局实例创建RngComponent,将内部Rng克隆到自身,这给它提供了一个随机但确定的种子。这允许在RngComponent之间有更好的随机状态,同时仍然有一个确定性的应用程序。

系统还需要正确排序才能保证确定性。然而,系统并不需要像线性路径一样严格排序。只有访问特定集合的 RngComponent 的相关系统需要排序。那些无关的系统可以并行运行,仍然能得到确定性的结果。因此,选择带有 RngComponentPlayer 实体的系统都应该相互排序,但选择带有 RngComponentItem 实体且从不与 Player 交互的系统,无需与 Player 系统排序,只需它们自己之间排序。

要查看此示例,请查看项目的测试用例 链接,了解如何利用确定性进行随机系统的测试。

支持版本

bevy_turborand bevy
v0.9.0-rc.1 v0.14.0-rc.4
v0.8 v0.13
v0.7 v0.12
v0.6 v0.11
v0.5 v0.10
v0.4 v0.9
v0.2, v0.3 v0.8
v0.1 v0.7

bevy_turborand 的 MSRV 与 bevy 相同,因此始终使用最新的 Rust 编译器版本。

从 0.2 版本迁移到 0.3 版本的指南

由于 API 的重构,turborand 0.6 版本有很多破坏性更改。大部分是 turborandbevy_turborand 的内部更改,而 bevy_turborand 默认公开了新特性,所以现有代码应该大致正常工作,除了以下内容:

  • RngComponent 上的 from_global 已不存在。取而代之的是,在 RngComponentChaChaRngComponent 上有 From 实现,覆盖了更多用例,其中可以使用引用、资源甚至另一个组件来初始化新的 RngComponent 等。这使得它在源的选择上更加灵活。只需使用 RngComponent::from 即可。
  • 不再接受 Option 参数的 new 函数。方法被分割在 new(用于不带种子初始化,因此获取随机种子)和 with_seed(用于带种子值初始化,适用于组件和资源)之间。
  • RngPlugin 现在采用构建器模式进行初始化。默认创建一个不带种子的默认状态,然后使用 with_rng_seedwith_chacha_seed 将种子值应用到插件上,然后使用这些种子值初始化全局 RNG 资源。请参阅文档以了解示例。
  • bevy_turborand 现在有一些功能标志,除了始终提供的新特性之外,其他所有内容都位于功能标志之后。例如,基于 wyrand 的结构(如 RngComponent 等)位于 wyrand 标志之后,该标志默认启用。为了获得更高质量的熵源(尽管它会更慢),chacha 标志提供 ChaCha8 算法提供的 RNG,例如 ChaChaRngComponent。当启用 wyrandchacha 时,RngPlugin 可用。否则,现有的标志如 rand 启用 rand crate 兼容层,而 serialize 用于 serde derive。

从 0.3 版本迁移到 0.4 版本的指南

bevy_turborand 已升级到 turborand 0.8,带来了一些重大的 API 破坏性更改。某些特性不再公开,因为它们是内部实现细节。主要变化是,ChaChaRng 不再由 Vec 缓存熵,而是切换到对齐数组以提高生成吞吐量,这略微牺牲了初始化性能和结构体大小。这意味着当 RNG 首次生成数字时,不需要单次堆分配。这次重构还改变了 ChaChaRng 的序列化方式,因此 bevy_turborand 0.4 与先前序列化的数据不兼容。

此外,TurboCore RNG 的旧 Clone 行为已更改,因此 .clone() 现在在原始实例和克隆实例之间保持状态。旧的行为现在作为 ForkableCore 特性存在,具有 .fork() 方法,该方法会修改原始实例的状态,以便为分叉实例推导新的随机状态。因此,RngComponentChaChaRngComponent 现在可以实现 Clone

从 0.4 迁移到 0.5 的指南

bevy_turborand 已升级到 turborand 0.10,引入了更多支持迭代器的样本/样本多次方法,partial_shuffle,以及关于稳定索引的重大更改,样本/洗牌方法使用新的 index 方法。 index 允许样本在平台之间稳定,尽管它目前针对 64 位系统进行了优化。所有样本/洗牌方法现在都使用 index,这意味着 bevy_turborand 在不同平台之间将是确定的,例如 wasm32x86-64 有相同的输出。唯一不受此影响的方法是 usize

ChaChaRngComponent 也因内部 ChaChaRng 源代码的改变而具有不同的输出,这也改变了它的序列化方式。

许可证

根据您的要求,受以下任一许可证的许可:

依赖项

~22MB
~408K SLoC