#async-task #async #bevy #gamedev #background-task #abstraction #context

bevy_async_task

Bevy中异步编程的便捷抽象

3 个不稳定版本

0.2.0 2024年7月5日
0.1.1 2024年5月1日
0.1.0 2024年3月24日

188游戏开发

Download history 63/week @ 2024-05-03 45/week @ 2024-05-10 95/week @ 2024-05-17 106/week @ 2024-05-24 85/week @ 2024-05-31 71/week @ 2024-06-07 45/week @ 2024-06-14 91/week @ 2024-06-21 72/week @ 2024-06-28 270/week @ 2024-07-05 167/week @ 2024-07-12 168/week @ 2024-07-19 99/week @ 2024-07-26 162/week @ 2024-08-02 172/week @ 2024-08-09 284/week @ 2024-08-16

每月下载量 733
用于 2 crates

Apache-2.0 OR MIT

36KB
456

Bevy Async Task

Discord MIT/Apache 2.0 Build status Dependency status crates.io docs.rs

为Bevy中的异步编程提供便捷抽象的最小crate。它为 wasmnative 提供了完整的API支持。Android和iOS尚未测试(需要帮助)。

Bevy Async Task提供了Bevy系统参数,以在后台运行异步任务,并支持超时和相同系统中的future输出。它还为在同步上下文中阻塞future时提供了语法糖,以减少样板代码。

Bevy版本支持

bevy bevy_async_task
0.14 0.2, main
0.13 0.1
<= 0.13 不支持

用法

这里有几个示例供参考。

您还可以在网络上运行示例

# Make sure the Rust toolchain supports the wasm32 target
rustup target add wasm32-unknown-unknown

cargo run_wasm --example simple

系统轮询

使用AsyncTaskRunner<T>逐个轮询一个任务

async fn long_task() -> u32 {
    sleep(Duration::from_millis(1000)).await;
    5
}

fn my_system(mut task_executor: AsyncTaskRunner<u32>) {
    match task_executor.poll() {
        AsyncTaskStatus::Idle => {
            task_executor.start(long_task());
            info!("Started new task!");
        }
        AsyncTaskStatus::Pending => {
            // <Insert loading screen>
        }
        AsnycTaskStatus::Finished(v) => {
            info!("Received {v}");
        }
    }
}

同时轮询许多类似任务使用AsyncTaskPool<T>

fn my_system(mut task_pool: AsyncTaskPool<u64>) {
    if task_pool.is_idle() {
        info!("Queueing 5 tasks...");
        for i in 1..=5 {
            task_pool.spawn(async move { // Closures work too!
                sleep(Duration::from_millis(i * 1000)).await;
                i
            });
        }
    }

    for status in task_pool.iter_poll() {
        if let AsyncTaskStatus::Finished(t) = status {
            info!("Received {t}");
        }
    }
}

此外,您还可以使用超时或阻塞在AsyncTask<T>

// Blocking:
let task = AsyncTask::new(async { 5 });
assert_eq!(5, task.blocking_recv());

// Timeout:
let task = AsyncTask::<()>::pending().with_timeout(Duration::from_millis(10));
assert!(task.blocking_recv().is_err());

需要手动引导吗?将任务分解成部分。

let task = AsyncTask::new(async move {
    sleep(Duration::from_millis(1000)).await;
    5
});
// Break the task into a runnable future and a receiver
let (fut, mut rx) = task.into_parts();
// The receiver will always be `None` until it is polled by Bevy.
assert_eq!(None, rx.try_recv());
// Run the future
let task_pool = bevy::prelude::AsyncComputeTaskPool::get();
let task = task_pool.spawn(fut);
task.detach(); // Forget and run in background
// Spin-lock, waiting for the result
let result = loop {
    if let Some(v) = rx.try_recv() {
        break v;
    }
};
assert_eq!(5, result);

社区

所有Loopy项目和开发都在Loopy Discord中进行。Discord对所有公众开放。

欢迎通过pull request进行贡献。适用Rust行为准则

许可证

根据您的选择许可

任选其一

贡献

除非您明确声明,否则根据Apache-2.0许可证定义,您有意提交用于包含在作品中的任何贡献,均应双许可如上所述,不附加任何额外条款或条件。

依赖项

~40–77MB
~1.5M SLoC