用途
本技能用于在 Bevy 0.20 中组织对话数据。当对话行、选项或说话者 id 需要推进时加载它。它只负责对话数据与推进逻辑,渲染对话行属于 bevy-ui-text 的职责。
主要能力
- 对话行表:整段对话的行定义(说话者、文本、下一行索引)存放在一个 Resource 中,而不是自动加载(autoload)。
- 当前行:用一个 Component 存储当前行索引,实现按对话实例推进。
- 选项过滤:选项作为行上的数据,当所需剧情标记(flag)不存在时隐藏该选项。
- 剧情标记:用 Resource 保存已获得的标记名,在展示选项前过滤。
- 消息:一次性事实(命中、拾取、任务推进)通过 bevy-events-messaging 处理,本技能不新增事件类型名。
使用方式
ECS 结构约定:
- Components:自定义的行 id 与说话者 id。
- Resources:全局范围的表放在 Resource 中(bevy-data-resources),不是 autoload。
- Systems:在 Update 或固定时间步上修改这些组件;当伤害必须先于死亡结算时使用 .chain()。
- Messages:一次性事实走 bevy-events-messaging。
依赖声明:
[dependencies]
bevy = "0.20"
行推进示例(节选):
#[derive(Clone)]
struct LineDef {
speaker: &'static str,
text: &'static str,
next: Option<usize>,
}
#[derive(Resource)]
struct DialogueTable {
lines: Vec<LineDef>,
}
#[derive(Component)]
struct LineMark {
index: usize,
open: bool,
}
选项过滤示例(节选):
fn shown_choices(flags: &StoryFlags, list: &ChoiceList) -> Vec<usize> {
list.choices
.iter()
.enumerate()
.filter_map(|(index, choice)| match choice.requires_flag {
Some(flag) if !flags.names.iter().any(|name| *name == flag) => None,
_ => Some(index),
})
.collect()
}
状态归属约定:
- 单个实体上的数据:Component,由某个系统通过 Query 修改,运行在 Update 或 FixedMain。
- 整个应用共享的一个值:Resource,由某个系统修改,Startup 插入,之后由读取它的调度使用。
- 生成:Commands,由生成系统负责;初始世界在 Startup,运行时生成在后续调度。
- 不能竞态的顺序:.chain(),仅约束被链式的系统,处于同一调度。
- 插件边界:Plugin,在 build 中注册系统与资源,在应用运行前完成。
借用规则:两个系统若都可变查询同一组件,必须用 .chain() 排序,或拆分使只有一个写入;无关系统保持并行。
适用场景
- 需要按行推进的对话流程。
- 需要根据剧情标记显示或隐藏选项。
- 需要区分说话者 id 的对话数据。
- 需要把对话数据与渲染分离的 Bevy 项目。
限制
- 目标版本为 Bevy 0.20+。
- 不负责富文本渲染,渲染属于 bevy-ui-text。
- 不新增事件类型,一次性事实使用 bevy-events-messaging。
- 不引入物理、导航、网络或 XR crate。
- 不使用 Godot 的节点、资源或信号类型;Bevy 代码保持惯用 ECS,仅使用有文档的 Bevy API。
- 不发明 API 或未命名的第三方 crate 作为解决方案。
- 文档 URL 不要固定 /0.20.0/,链接保持在最新站点,0.20 目标只在正文中说明一次。
相关技能
前置:bevy-master(枢纽与调度)、bevy-ecs-composition(组件与系统)、bevy-ui-text(绘制行)、bevy-quest-system(任务门控)、bevy-data-resources(表与定义)、bevy-events-messaging(一次性事实)。
互补:bevy-state-machines(模式标记)、godot-dialogue-system(等价的 Godot 技能)。
下游/消费者:暂未提供。
主技能:bevy-master(Bevy 路由)。