任务追踪
一个任务日志:每个任务显示完成了没有,玩家的金币显示在画面上,完成任务就发奖励、弹提示。任务完成没有由 AI 判断,奖励由行为发,而且只发一次,玩家界面里有一页显示任务日志。不用写代码。
你要做的东西
- 任务日志页:「采草药」和「打败森林狼」,每个都显示已完成或还没完成
- 金币显示在画面上,奖励一到就更新
- AI 来标记任务完成:剧情里真的发生了就算,不管玩家怎么说的
- 奖励只发一次:草药 +30 金币,狼 +50 金币,同时弹一个提示
- 进度计数:「完成 1 / 2」
怎么运作
玩家把草药交给村长
→ AI 按照 Quests done 变量的行为规则,把「采草药」加进列表
→ 行为「奖励:采草药」在盯着 Quests done(变量变化)
→ 条件成立(Quests done 包含「采草药」),而且它还没触发过(最大触发次数 1)
→ Gold +30,弹出提示「任务完成:采草药(+30 金币)」,同时告诉 AI
→ 任务日志上「采草药」显示已完成判断剧情里有没有发生某件事,AI 很拿手;只发一次钱,引擎很拿手。
一步一步来
第 1 步:建变量
点卡底下 还可以加 里的 + 变量,下面每个建一次。
Quests done
| 字段 | 值 |
|---|---|
| 名称 | Quests done |
| 类型 | 列表/表格 |
| 初始值 | [] |
| 行为规则 | 见下面 |
玩家已经完成的任务,按名字记。任务有两个:「采草药」(把治伤的草药带给村长)和「打败森林狼」(杀掉那头一直叼羊的狼)。玩家在剧情里真的完成了其中一个,就把它的名字原样加进这个列表。没完成的任务不要加,同一个任务不要加两次。Gold
| 字段 | 值 |
|---|---|
| 名称 | Gold |
| 类型 | 数值 |
| 初始值 | 0 |
| 范围 | 0 到(不填) |
| 行为规则 | 玩家的金币。任务奖励会自动加上;捡到战利品、做买卖、被偷的时候你也可以改它。 |
点 放到玩家界面上,让金币一直显示在聊天里。
Quests completed(可选)
| 字段 | 值 |
|---|---|
| 名称 | Quests completed |
| 类型 | 数值 |
| 公式(自动算) | len({Quests done}) |
它自己数列表里有几个。AI 看得到,但改不了。
第 2 步:每个任务建一条奖励行为
点 还可以加 里的 + 行为。
奖励:采草药
| 部分 | 设置 |
|---|---|
| 什么时候触发 | 变量变化:Quests done |
| 如果…… | Quests done 包含 采草药 |
| 效果 | 修改变量:Gold 加上 30 |
显示通知:任务完成:采草药(+30 金币),样式选 成功 | |
告诉 AI:玩家刚完成了「采草药」,拿到 30 金币。在回复里提一下。 | |
| 最大触发次数 | 1 |
奖励不会发两次,靠的是 最大触发次数 1:下一个任务加进来时列表又变了一次,那时「包含采草药」还是成立的,但这条行为已经触发过一次了。
告诉 AI 会给 AI 塞一句话,只管下一次回复,这样它就能写村长数钱给你的样子。
奖励:打败森林狼
和上面一样,条件里换成 打败森林狼,Gold 加上 50,提示和给 AI 的那句话也对应改一下。
也可以用关键词触发
也可以靠对话里的词来完成任务:什么时候触发 选 AI 说出关键词 村长接过草药。关键词用逗号隔开,任意一个 出现就会触发,所以写成 打败, 狼 的话,「我看到一头狼」也会触发。要用只在那一刻才会出现的说法,再给每个任务配一个开关变量(在效果里设成开,在 如果…… 里检查),免得触发两次。像上面那样让 AI 来标记任务,更能应付玩家五花八门的说法。
第 3 步:做任务日志页
点顶栏中间的 玩家界面。用 新建一页 加一页(选 空白页),起名叫「任务」。
- 加一个 文字 部件当标题,再加一个写着
完成 {Quests completed} / 2的(用 插入变量的值…) - 加一个 列表 部件。内容从哪来 选 自己写几行,加两行:标题
采草药,正文把治伤的草药带给村长。奖励:30 金币;标题打败森林狼,正文杀掉那头一直叼羊的狼。奖励:50 金币 - 打开 每一行画成一张卡
- 在 锁住直到 里打开 没解锁的行显示成锁住,看哪个变量 选 Quests done,对照这一行的哪个字段 保持
title不动。锁住时显示 写还没完成。Quests done 里有这一行的标题,这一行就亮起来 - 加一个按钮,步骤选 跳到页面,跳回对话页;再在对话页上加一个「任务」按钮,跳到页面 → 任务
把 编辑 关掉,就能点着试试,不花额度。
整个界面的布局
如果想让金币和别的数值一直显示在画面上,而不是放在单独一页,可以用 整个界面 里的 养成面板 模板,它自带四条状态、金币和天数。
第 4 步:试玩
点顶栏的 试玩。
- 打开 任务:两个任务都是「还没完成」,完成 0 / 2,Gold 0
- 把找草药、送回去这段剧情玩一遍。AI 标记任务的时候,提示弹出来,Gold 变成 30
- 打开 任务:采草药已完成,1 / 2
- 去把狼解决掉。Gold 变成 80,2 / 2
试玩右边的 这回合 能看到 Quests done 什么时候变了,每条奖励行为有没有触发。
如果出了问题:
| 现象 | 可能的原因 | 怎么改 |
|---|---|---|
| 剧情里任务做完了,但一直没标记 | AI 没把它加进列表 | 在行为规则里把每个任务的名字写准,并说清楚什么情况才算完成 |
| 标记了,但没发奖励 | AI 加进去的名字和条件对不上 | 列表里的名字、条件、列表行的标题,三处要是一样的字 |
| 奖励发了两次 | 最大触发次数 不是 1 | 每条奖励行为都设上 |
| 日志那一行一直锁着 | 对照这一行的哪个字段 或 看哪个变量 选错了 | title,和 Quests done |
| AI 太早标记任务完成 | 规则写得太松 | 写清楚要发生什么:「只有草药交到村长手里才算」 |
写代码的做法:聊天下方的任务面板
如果你自己写界面,就在界面代码里读同样的变量。上面做的东西都不用改。
面板 → 前端代码 → 打开 index.tsx,把默认的 return <Chat /> 换掉:
export default function MyWorld() {
const api = useYumina();
const msgs = api.messages || [];
const done = Array.isArray(api.variables["Quests done"])
? api.variables["Quests done"].map(String)
: [];
const gold = Number(api.variables["Gold"] ?? 0);
const quests = [
{ name: "采草药", reward: 30 },
{ name: "打败森林狼", reward: 50 },
].map((q) => ({ ...q, done: done.includes(q.name) }));
const completedCount = quests.filter((q) => q.done).length;
return (
<Chat renderBubble={(msg) => {
const isLastMsg = msg.messageIndex === msgs.length - 1;
return (
<div>
<div
style={{ color: "#e2e8f0", lineHeight: 1.7 }}
dangerouslySetInnerHTML={{ __html: msg.contentHtml }}
/>
{isLastMsg && (
<div style={{
marginTop: "16px",
padding: "16px",
background: "linear-gradient(135deg, rgba(30,41,59,0.8), rgba(15,23,42,0.9))",
borderRadius: "12px",
border: "1px solid #334155",
}}>
{/* 标题和金币 */}
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "14px" }}>
<div style={{ fontSize: "15px", fontWeight: "bold", color: "#e2e8f0" }}>任务追踪</div>
<div style={{
display: "flex", alignItems: "center", gap: "6px", padding: "4px 12px",
background: "rgba(234,179,8,0.15)", border: "1px solid rgba(234,179,8,0.3)", borderRadius: "20px",
}}>
<span style={{ fontSize: "14px" }}>💰</span>
<span style={{ fontSize: "14px", fontWeight: "bold", color: "#fbbf24" }}>{gold}</span>
</div>
</div>
<div style={{ fontSize: "12px", color: "#64748b", marginBottom: "12px" }}>
已完成 {completedCount}/{quests.length}
</div>
{/* 任务列表 */}
<div style={{ display: "flex", flexDirection: "column", gap: "8px" }}>
{quests.map((quest) => (
<div key={quest.name} style={{
display: "flex", justifyContent: "space-between", alignItems: "center",
padding: "10px 14px", borderRadius: "8px",
background: quest.done ? "rgba(34,197,94,0.08)" : "rgba(30,41,59,0.5)",
border: quest.done ? "1px solid rgba(34,197,94,0.2)" : "1px solid #1e293b",
}}>
<span style={{
fontSize: "13px",
color: quest.done ? "#94a3b8" : "#e2e8f0",
textDecoration: quest.done ? "line-through" : "none",
}}>
{quest.name}
</span>
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
<span style={{ fontSize: "12px", color: quest.done ? "#4ade80" : "#64748b" }}>
{quest.done ? `+${quest.reward} 金币` : `${quest.reward} 金币`}
</span>
<span style={{
display: "inline-flex", alignItems: "center", justifyContent: "center",
width: "24px", height: "24px", borderRadius: "6px", fontSize: "13px", fontWeight: "bold",
background: quest.done ? "rgba(34,197,94,0.2)" : "rgba(239,68,68,0.15)",
color: quest.done ? "#4ade80" : "#f87171",
border: quest.done ? "1px solid rgba(34,197,94,0.3)" : "1px solid rgba(239,68,68,0.25)",
}}>
{quest.done ? "✓" : "✗"}
</span>
</div>
</div>
))}
</div>
{completedCount === quests.length && (
<div style={{
marginTop: "12px", padding: "10px", textAlign: "center", fontSize: "13px", fontWeight: "600",
background: "rgba(34,197,94,0.1)", border: "1px solid rgba(34,197,94,0.25)",
borderRadius: "8px", color: "#4ade80",
}}>
任务全部完成!
</div>
)}
</div>
)}
</div>
);
}} />
);
}代码做了什么:
api.variables["Quests done"]按变量名读这个列表,任务的名字在里面就算完成api.variables["Gold"]读金币completedCount数一数完成了几个,用在进度那一行和「全部完成」的横条上- 面板只出现在最后一条消息下面,变量一变就跟着更新
面板 → 前端代码 里文件旁边的状态应该是绿色的 正常。
不想自己写代码?
点画布右上角的 创作助手,说说你想要什么样的面板。
再往前走一步
更多任务
在 Quests done 的行为规则里加上新任务的名字和怎样算完成,加一条奖励行为,再在任务日志里加一行(或者在代码的 quests 数组里加一项)。如果用了公式,把日志页上的 / 2 改成新的总数。
AI 发出来的任务
再加一个列表 Quests open,在它的行为规则里告诉 AI:有角色请玩家帮忙时,把这个任务加进来。在日志页上再放一个列表部件显示它,内容从哪来 选 读一个变量(Quests open),而不是自己写几行。
任务链
想让「拯救村子」在草药之后才出现,就把新任务写成一条待命设定(等行为来叫,AI 才看得到)。然后加一条行为:变量变化 盯 Quests done,如果…… Quests done 包含 采草药,效果 启用词条 选那条设定,最大触发次数 1。从这以后 AI 就知道村长有了新请求。如果…… 里可以放好几个条件,选 全部满足 或 任一满足,用来做更长的链。待命设定见开场白和设定。
把金币花掉
商店用的是同一个 Gold 变量:任务往里加,商店往外扣。
速查
| 你想要 | 怎么做 |
|---|---|
| 让 AI 判断任务什么时候完成 | 一个列表/表格变量,行为规则里写清每个任务的名字 |
| 奖励只发一次 | 行为:变量变化,如果…… 列表 包含 这个任务,最大触发次数 1 |
| 告诉玩家 | 效果:显示通知,样式选 成功 |
| 告诉 AI | 效果:告诉 AI(只管下一次回复) |
| 数一数完成了几个 | 一个数值变量,公式填 len({Quests done}) |
| 显示任务日志 | 一个列表部件,自己写几行,锁住直到 看 Quests done |
| 金币一直显示在画面上 | 在 Gold 上点 放到玩家界面上 |
| 靠一句原话完成任务 | 玩家说出关键词 / AI 说出关键词(任意一个关键词出现就触发) |
| 自己画的面板 | 读同样变量的界面代码 |
自己试试:可导入的演示
下载这个 JSON 导入进去,就能看到能跑的版本:
怎么导入:
- 点左边的 创建,选 空白项目,再选 画布
- 在顶栏点 ⋮ → 导入文件,选下载好的
.json文件。它会替换掉这张新卡里的所有内容 - 点 保存,再点 试玩
演示用的是关键词触发的行为,每个任务一个开关变量,任务面板写在界面代码里。
这是食谱 #6
同一个循环(AI 发现某件事发生了,行为只发一次奖励,界面把它显示出来)也能用在剧情节点、支线任务树,还有成就上。
