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 游戏开发
每月650次下载
在 3 个crate 中使用
47KB
591 行
bevy_turborand
一个为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进行初始化。可以给GlobalRng和RngPlugin提供一个种子,然后设置内部PRNG以表现出确定性。无需手动初始化每个RngComponent,只要初始化了GlobalRng,就可以直接从全局实例创建RngComponent,将内部Rng克隆到自身,这给它提供了一个随机但确定的种子。这允许在RngComponent之间有更好的随机状态,同时仍然有一个确定性的应用程序。
系统还需要正确排序才能保证确定性。然而,系统并不需要像线性路径一样严格排序。只有访问特定集合的 RngComponent 的相关系统需要排序。那些无关的系统可以并行运行,仍然能得到确定性的结果。因此,选择带有 RngComponent 的 Player 实体的系统都应该相互排序,但选择带有 RngComponent 的 Item 实体且从不与 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 版本有很多破坏性更改。大部分是 turborand 和 bevy_turborand 的内部更改,而 bevy_turborand 默认公开了新特性,所以现有代码应该大致正常工作,除了以下内容:
RngComponent上的from_global已不存在。取而代之的是,在RngComponent和ChaChaRngComponent上有From实现,覆盖了更多用例,其中可以使用引用、资源甚至另一个组件来初始化新的RngComponent等。这使得它在源的选择上更加灵活。只需使用RngComponent::from即可。- 不再接受 Option 参数的
new函数。方法被分割在new(用于不带种子初始化,因此获取随机种子)和with_seed(用于带种子值初始化,适用于组件和资源)之间。 RngPlugin现在采用构建器模式进行初始化。默认创建一个不带种子的默认状态,然后使用with_rng_seed和with_chacha_seed将种子值应用到插件上,然后使用这些种子值初始化全局 RNG 资源。请参阅文档以了解示例。bevy_turborand现在有一些功能标志,除了始终提供的新特性之外,其他所有内容都位于功能标志之后。例如,基于wyrand的结构(如RngComponent等)位于wyrand标志之后,该标志默认启用。为了获得更高质量的熵源(尽管它会更慢),chacha标志提供 ChaCha8 算法提供的 RNG,例如ChaChaRngComponent。当启用wyrand或chacha时,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() 方法,该方法会修改原始实例的状态,以便为分叉实例推导新的随机状态。因此,RngComponent 和 ChaChaRngComponent 现在可以实现 Clone。
从 0.4 迁移到 0.5 的指南
bevy_turborand 已升级到 turborand 0.10,引入了更多支持迭代器的样本/样本多次方法,partial_shuffle,以及关于稳定索引的重大更改,样本/洗牌方法使用新的 index 方法。 index 允许样本在平台之间稳定,尽管它目前针对 64 位系统进行了优化。所有样本/洗牌方法现在都使用 index,这意味着 bevy_turborand 在不同平台之间将是确定的,例如 wasm32 和 x86-64 有相同的输出。唯一不受此影响的方法是 usize。
ChaChaRngComponent 也因内部 ChaChaRng 源代码的改变而具有不同的输出,这也改变了它的序列化方式。
许可证
根据您的要求,受以下任一许可证的许可:
- Apache License,版本 2.0 (LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 https://open-source.org.cn/licenses/MIT)
。
依赖项
~22MB
~408K SLoC