8个版本 (5个重大变更)
0.6.0 | 2024年8月13日 |
---|---|
0.5.1 | 2024年6月4日 |
0.5.0 | 2024年2月18日 |
0.4.1 | 2024年1月24日 |
0.1.0 | 2023年12月1日 |
#341 in 游戏开发
每月下载 165次
用于 haalka
51KB
1K SLoC
🔄 Bevy Async ECS
什么是Bevy Async ECS?
Bevy Async ECS是标准Bevy World
的异步接口。它旨在为熟悉Bevy ECS的用户提供简单直观的使用体验。
AsyncWorld
AsyncWorld
是进一步异步操作世界入口点。它只能通过使用FromWorld
trait实现来创建。它应由与主Bevy应用并行运行的可执行器驱动(这可以是TaskPool
之一或运行在另一个线程上的阻塞可执行器)。
内部,AsyncWorld
只是封装了一个MPSC通道发送者。因此,它可以便宜地克隆并进一步发送到不同的线程或任务。这意味着所有对AsyncWorld
的操作都以FIFO顺序处理。然而,没有在AsyncWorld
之间或共享相同内部通道发送者的任何衍生品之间,或者任何单独构建的AsyncWorld
之间的顺序保证。
需要注意的是,当异步任务运行时,Bevy仍在运行并修改世界!假设世界可能在任何异步调用之间被修改。然而,有几种方法可以确保多个命令一起应用,而不在之间修改世界。
- 构建一个纯Bevy
CommandQueue
,然后通过CommandQueueSender::send_queue()
将其发送到BevyWorld
- 通过
AsyncWorld::start_queue()
使用由AsyncWorld
提供的队列构建器
基本示例
use bevy::prelude::*;
use bevy::tasks::AsyncComputeTaskPool;
use bevy_async_ecs::*;
// vanilla Bevy system
fn print_names(query: Query<(Entity, &Name)>) {
for (id, name) in query.iter() {
info!("entity {:?} has name '{}'", id, name);
}
}
fn main() {
App::new()
.add_plugins((DefaultPlugins, AsyncEcsPlugin))
.add_systems(Startup, |world: &mut World| {
let async_world = AsyncWorld::from_world(world);
let fut = async move {
let print_names = async_world.register_system(print_names).await;
let entity = async_world.spawn_named("Frank").await;
print_names.run().await;
entity.despawn().await;
};
AsyncComputeTaskPool::get().spawn(fut).detach();
})
.run();
}
多线程
bevy-async-ecs
不明确要求multi-threaded
功能(尽管所有测试和示例都这么做)。然而,当任务执行器在单个线程上运行时(例如在wasm上),异步世界可能会发生死锁。如果这是您的一个痛点,请打开一个GitHub问题。
最近兼容的版本
bevy | bevy-async-ecs |
---|---|
0.14 | 0.6.0 |
0.13 | 0.5.1 |
0.12 | 0.4.1 |
0.11 | N/A |
依赖项
~12MB
~202K SLoC