DUAN 是一个面向复杂规则推演的 Rust 仿真运行时内核。
它关注仿真系统里最难长期维护的部分:对象如何表达状态和意图,规则如何裁定事实,事件如何记录变化,每一轮推演如何保持稳定、可解释和可复现。
实体表达意图,域裁定事实。
DUAN 适合用作体系仿真、任务推演、调度仿真、规则驱动性能仿真等自研平台的底层运行时。
典型场景包括:
- 多类对象持续演化,例如装备、节点、任务、资源、目标或流程实例。
- 多组业务规则共同裁定结果,例如机动、探测、通信、消耗、保障、调度等。
- 需要明确说明“谁提出动作、谁裁定结果、哪些变化已经发生”的推演系统。
- 需要反复运行同一场景并比较策略、参数和规则差异的工程系统。
在项目中添加依赖:
[dependencies]
duan = "0.1"日常开发推荐导入 prelude:
use duan::prelude::*;最小示例:
use duan::prelude::*;
#[derive(Clone, Default)]
struct Position {
y: f64,
}
duan::reality!(Position);
struct Ball;
impl Entity for Ball {
fn bundle() -> impl ComponentBundle + Send + 'static {
(Position { y: 10.0 },)
}
}
struct Gravity;
impl Domain for Gravity {
type Writes = duan::component_set!(Position);
type Reads = duan::component_set!(Position);
type After = duan::domain_set!();
fn compute(&mut self, ctx: &mut DomainContext<Self>, delta_time: f64) {
let ids: Vec<_> = ctx.entities::<Position>().collect();
for id in ids {
if let Some(position) = ctx.get_mut::<Position>(id) {
position.y -= 9.8 * delta_time;
}
}
}
}
let mut world = World::builder().domain(Gravity).build();
let ball = world.spawn::<Ball>();
world.step(0.016);
let position = world.get::<Position>(ball).unwrap();
println!("ball.y = {:.3}", position.y);运行仓库示例:
cargo run --manifest-path examples/free_fall/Cargo.toml
cargo run --manifest-path examples/naval_combat/Cargo.tomlDUAN 把仿真系统拆成几个稳定角色:
| 角色 | Rust 类型 | 说明 |
|---|---|---|
| 世界 | World |
仿真的顶层容器,负责时间推进、实体、存储、调度、事件和生命周期。 |
| 实体 | Entity |
仿真对象模板,定义初始组件和可选的每帧意图表达。 |
| 组件 | Component |
附着在实体上的数据,按 Belief、Intent、Reality 三类语义组织。 |
| 域 | Domain |
规则权威,读取阶段快照并写入自己声明负责的事实组件。 |
| 事件 | Event |
描述已经发生的变化,由 Reaction 和 Observer 在事件阶段消费。 |
| 快照 | Snapshot |
阶段稳定的只读世界视图,避免同一阶段内读到半提交状态。 |
三类组件语义:
Belief:实体内部认知,不进入快照。Intent:实体对外表达的意图,可被域从快照读取。Reality:世界事实,只能由声明负责的域写入。
当前本机 Criterion 基准显示:常规万级对象推演通常处于毫秒级以内到约 1.5ms,复杂综合管线约 7ms,极端大量新增/销毁场景约 10-12ms。
这些数字用于说明当前内核量级,不构成对所有机器和所有业务模型的性能承诺。完整说明见 性能说明。
正式用户文档位于 docs/duan-docs。
DUAN 采用 MIT 许可证。使用、修改和分发本项目时,需要保留相应的版权与许可声明。