実績システム
プレイヤーが節目に届いたとき(ゴールドが 100 を超えた、戦闘に 5 回以上勝った、隠しエリアを見つけた)、実績の名前とひとことが書かれたカードが出てきます。実績はそれぞれ一度だけ解放されてリストに入り、プレイヤー画面のページで、見つけたものとまだロックされているものを確認できます。どれもコードなしで作れます。
作るもの
- 節目に届いた瞬間に出るポップアップ:タイトル、ひとこと、必要なら画像の付いた小さなカード
- 自動で判定:ビヘイビアが数値と会話を見ているので、プレイヤーは何もしなくて大丈夫です
- 実績は一度だけ解放:すでにリストに入っている場面は、二度と出てきません
- 実績ページ:すべての実績が並び、解放したものは本文、ロック中のものはヒントが表示されます
- 任意:新しくプレイを始めても解放したままの実績
しくみ
プレイヤーのゴールドが 95 から 101 になる
→ ビヘイビア「Big Spender」が Gold を見ている(変数がしきい値を越える、上回る 100)
→ 効果「ひとつの場面を解放」でカード「Big Spender」が出る
→ タイトル「Big Spender」がリスト変数 Achievements に追加される
→ 実績ページで Big Spender が解放済みになる数値は物語の流れに合わせて AI が動かしますが、実績を解放するかどうかはエンジンが決めます。なので、実績が忘れられたり、二重に渡されたりすることはありません。
手順
ステップ 1:変数を作る
カードの下にある 追加できるもの から、次の変数をひとつずつ + 変数 で追加します。
Gold
| 項目 | 値 |
|---|---|
| 名前 | Gold |
| 型 | 数値 |
| 初期値 | 0 |
| 範囲 | 0 から(上限は空欄) |
| ビヘイビアルール | プレイヤーの所持ゴールド。報酬をもらったとき、戦利品を得たとき、何かを売ったときに増え、お金を使うと減る。 |
Battles won
| 項目 | 値 |
|---|---|
| 名前 | Battles won |
| 型 | 数値 |
| 初期値 | 0 |
| ビヘイビアルール | プレイヤーが戦闘に勝った回数。プレイヤーがはっきり勝ったときに 1 増やす。 |
Achievements
| 項目 | 値 |
|---|---|
| 名前 | Achievements |
| 型 | リスト/表 |
| 初期値 | [] |
AI での扱い を開き、AI アクセス を エンジン専用(AI に非表示) にします。このリストに書き込むのはビヘイビアだけで、AI が読む必要もありません。
新しくプレイしても残る実績
同じ欄で 周回をまたいで保持(プレイヤーごと) にチェックを入れます。こうすると、プレイヤーが最初からやり直しても、リストはそれまでに解放した実績から始まり、その実績がもう一度出てくることもありません。CG ギャラリーや「見たエンディング」のコレクションも、このしくみで作ります。
ステップ 2:実績ごとにビヘイビアを作る
追加できるもの から + ビヘイビア を押します。
ビヘイビア 1:Big Spender
| 部分 | 設定 |
|---|---|
| 発動するとき | 変数がしきい値を越える:Gold、上回る、100 |
| 効果 | ひとつの場面を解放 |
場面の中身を入れます。
| 項目 | 値 |
|---|---|
| タイトル | Big Spender |
| メッセージ | ゴールドを 100 より多く貯めた。 |
| 画像(リンク) | 任意:https:// のリンクか、パネル → アセット のアセット |
| どのリストに集めるか | Achievements |
「変数がしきい値を越える」が発動するのは、数値が 100 以下から 100 より大きくなったその瞬間だけです。ゴールドがそのまま 101 から 150 へ増えても、何も起きません。ゴールドが 100 未満に戻ってからまた増えれば再び発動しますが、場面はもう Achievements に入っているので、何も出てきません。
ビヘイビア 2:Seasoned Fighter
| 部分 | 設定 |
|---|---|
| 発動するとき | 変数がしきい値を越える:Battles won、上回る、5 |
| 効果 | ひとつの場面を解放:タイトル Seasoned Fighter、メッセージ 戦闘に 5 回より多く勝った。、集めるリストは Achievements |
ビヘイビア 3:Trailblazer(キーワード)
これは数値ではなく会話を見ます。ビヘイビアのトリガーは 1 つだけなので、プレイヤーの発言と AI の発言の両方を拾うには、ビヘイビアを 2 つ作ります。
3a
| 部分 | 設定 |
|---|---|
| 発動するとき | プレイヤーがキーワードを発言:探索, 洞窟を調べる |
| 効果 | ひとつの場面を解放:タイトル Trailblazer、メッセージ 隠されたものを探しに行った。、集めるリストは Achievements |
3b
| 部分 | 設定 |
|---|---|
| 発動するとき | AIがキーワードを発言:隠し通路, 秘密の部屋 |
| 効果 | 3a と同じ ひとつの場面を解放。タイトルも同じにします |
キーワードはカンマで区切り、どれか 1 つが出れば発動します。2 つのビヘイビアは同じタイトルで同じリストに集めるので、先に発動したほうが実績を解放し、もう一方はすでに入っているのを見て何もしません。そのための条件を追加する必要はありません。
場面と通知、どちらを使う?
「実績解除」と一行出すだけなら、通知を表示(スタイルは 成功)でもできます。ただ、通知は何も覚えていません。実績ごとにスイッチ変数を用意し、二度発動しないように条件を付け、最大発動回数 を 1 にする必要があります。ひとつの場面を解放 なら、覚えておく部分を代わりにやってくれます。
ステップ 3:実績ページを作る
上部バー中央の プレイヤー画面 を押します。ページを追加 でページを足し(白紙のページ で大丈夫です)、タイトルを付けて、部品を追加 から リスト を置きます。
- 中身の出どころ で 自分で書く を選び、実績ごとに 1 行ずつ追加します。
Big Spender、Seasoned Fighter、Trailblazerに、それぞれ一行の本文を付けます - 各行をカードで表示 をオンにします
- ロック解除の条件 で 未解除の行をロック表示 をオンにします。見張る変数 を Achievements にし、照合する行の項目 は
titleのままにします。リストにその行のタイトルが入ると、その行が解放されます。ひとつの場面を解放 がリストに入れるのも、まさにこのタイトルです - ロック中の表示 に、解放前にプレイヤーが見るヒントを書きます。たとえば「少し貯金してみよう」
- 会話に戻る ページへ移動 の ボタン を置いて、行き止まりにならないようにします(置かないと、ページの列に 出口なし の注意が出ます)
- 会話のページに「実績」と書いた ボタン を置き、その手順を ページへ移動 → 作ったページにします
物語の中で AI が収集品を渡す作りなら、ビヘイビアを使う代わりに コレクション テンプレートから始めましょう。「集めるものは最初は灰色。物語で見つけるたびに光ります。」というテンプレートで、専用のリスト変数とポップアップ、それに AI がいつリストに追加するかを書いたビヘイビアルールが付いています。
上の 編集 をオフにすると、プレイヤーと同じようにページを操作して確かめられます。
数を数える
「Achievements unlocked」という数値の変数を追加し、計算式(自動で計算) に len(Achievements) と入れます。ページの文字の部品に {Achievements unlocked} / 3 と書けば、解放数が自動で更新されます。
ステップ 4:プレイテスト
上部バーの プレイ を押します。
- 実績 を押します。3 つともロックされていて、ヒントが表示されています
- ゴールドが 100 を超えるまで遊びます。「Big Spender」のカードが出て、ページでも解放済みになります
- 戦闘に 6 回勝ちます。Battles won が 5 から 6 になったところで「Seasoned Fighter」が出ます
- 「この洞窟を探索したい」と送ります。「Trailblazer」が出ます。あとで AI が隠し通路のことを話しても、もう一度出ることはありません
プレイテストの右側にある このターン で、どのビヘイビアが発動したか、発動しなかったのはなぜかを確認できます。
うまくいかないとき:
| 症状 | 考えられる原因 | 直し方 |
|---|---|---|
| ゴールドが 100 を超えているのに何も出ない | ゴールドが線を越えていない。最初から 100 より上だった | しきい値は越えた瞬間にだけ発動します。初期値 がしきい値以下になっているか確認します |
| 場面は出たのにページが変わらない | どのリストに集めるか が空になっている、またはページが別の変数を見ている | どちらも Achievements を選びます |
| 出てきたのにページではロックのまま | 行のタイトルと場面のタイトルが完全には一致していない | 大文字・小文字も含めて同じにします |
| 実績が二度出た | 2 つのビヘイビアでタイトルかリストが違う | タイトルもリストも同じにします |
コードで作る場合:チャットの下に実績パネルを出す
パネルを自分で描きたい場合、たとえば別ページではなく最後のメッセージの下に出したい場合は、画面のコードで書きます。上のビヘイビアはそのままで、コードは Achievements のリストを読むだけです。
パネル → フロントエンドコード で index.tsx を開き、デフォルトの return <Chat /> を置き換えます。
export default function MyWorld() {
const api = useYumina();
const msgs = api.messages || [];
// Titles must match the moment titles in your behaviors
const achievements = [
{ title: "Big Spender", desc: "Save more than 100 gold", icon: "💰" },
{ title: "Seasoned Fighter", desc: "Win more than 5 battles", icon: "⚔️" },
{ title: "Trailblazer", desc: "Find a hidden area or secret", icon: "🗺️" },
];
// The list the moments are collected into, read by its name
const unlockedList = Array.isArray(api.variables["Achievements"])
? api.variables["Achievements"].map(String)
: [];
const isUnlocked = (a) => unlockedList.includes(a.title);
const unlockedCount = achievements.filter(isUnlocked).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: "12px 16px",
background: "linear-gradient(135deg, #1c1917, #292524)",
border: "1px solid #44403c",
borderRadius: "10px",
}}>
<div style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
marginBottom: "10px",
}}>
<span style={{ fontSize: "13px", fontWeight: "bold", color: "#fbbf24" }}>
🏆 Achievements
</span>
<span style={{ fontSize: "12px", color: "#a8a29e" }}>
{unlockedCount} / {achievements.length}
</span>
</div>
<div style={{ display: "flex", flexDirection: "column", gap: "6px" }}>
{achievements.map((a) => {
const unlocked = isUnlocked(a);
return (
<div
key={a.title}
style={{
display: "flex",
alignItems: "center",
gap: "10px",
padding: "6px 8px",
borderRadius: "6px",
background: unlocked
? "rgba(251, 191, 36, 0.08)"
: "rgba(120, 113, 108, 0.08)",
}}
>
<span style={{ fontSize: "18px", opacity: unlocked ? 1 : 0.3 }}>
{unlocked ? a.icon : "🔒"}
</span>
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{
fontSize: "13px",
fontWeight: "600",
color: unlocked ? "#fbbf24" : "#78716c",
}}>
{a.title}
</div>
<div style={{
fontSize: "11px",
color: unlocked ? "#a8a29e" : "#57534e",
marginTop: "1px",
}}>
{a.desc}
</div>
</div>
{unlocked && (
<span style={{ fontSize: "11px", color: "#fbbf24" }}>✓ Unlocked</span>
)}
</div>
);
})}
</div>
</div>
)}
</div>
);
}} />
);
}コードがしていること:
<Chat renderBubble={...} />で、プラットフォームのメッセージ一覧、入力欄、スクロールはそのまま使い、吹き出しの中身だけを自分で描きますmsg.messageIndex === msgs.length - 1で、パネルを最後のメッセージの下にだけ出しますmsg.contentHtmlは、HTML に変換済みのメッセージですapi.variables["Achievements"]で、変数名を使ってリストを読みます。スペースや大文字を含む名前も、このかっこの書き方なら読めます- 実績は、タイトルがリストに入っていれば解放済みとみなします。場面と同じ判定です
パネル → フロントエンドコード のファイル名の横の表示が、緑の OK になっていれば大丈夫です。エラー になっているときは、その下のメッセージに何行目かが書いてあります。
コードを自分で書きたくないときは
キャンバス右上の AIアシスタント を押して、ほしいパネルを説明してください。画面のコードを書いてくれます。
「変数がしきい値を越える」と「変数が変化」の違い
どちらも変数を見るトリガーですが、発動するタイミングが違います。
変数がしきい値を越える は、数値がある線を越えたその瞬間に発動します。
gold: 80 → 95 → 101 ← 95→101 で発動(100 を上に越えた)
gold: 101 → 150 → 200 ← 発動しない(もう上にいる)
gold: 200 → 50 → 120 ← 50→120 で発動(もう一度 100 を上に越えた)節目、警告(「体力が 20 を下回った」)、死亡判定に使います。
変数が変化 は、選んだ変数が変わるたびに、値に関係なく発動します。
gold: 80 → 95 ← 発動
gold: 95 → 101 ← 発動
gold: 101 → 150 ← 発動役に立てるには 次の場合のみ の条件(「Gold ≥ 100 の場合のみ」)が必要で、変わるたびに毎回チェックし直します。実績で大事なのは線を越えた瞬間なので、変数がしきい値を越える のほうが自然に合います。
実績を増やす
実績を 1 つ増やすには、ビヘイビアを 1 つと実績ページの行を 1 つ足します。
| 実績 | 発動するとき |
|---|---|
| おしゃべり好き | Nターンごと:50、最大発動回数 は 1 |
| ため込み屋 | 変数がしきい値を越える:Gold が 500 を上回る |
| 人気者 | AIがキーワードを発言:あなたを信頼, 友達になる |
| 九死に一生 | 変数がしきい値を越える:Health が 10 を下回ったらスイッチ「死にかけた」をオンにする。2 つめのビヘイビアで Health が 50 を上回ったとき、次の場合のみ「死にかけた」がオン、の条件で場面を解放する |
早見表
| やりたいこと | やり方 |
|---|---|
| 数値が目標に届いたら解放 | 発動するとき:変数がしきい値を越える、上回る |
| 何かが話されたら解放 | プレイヤーがキーワードを発言 か AIがキーワードを発言 |
| カードを出して覚えておく | 効果:ひとつの場面を解放、どのリストに集めるか を指定 |
| 一度しか解放しないようにする | タイトルもリストも同じにします。リストに入っているタイトルの場面は発動しません |
| 新しくプレイしても実績を残す | リスト変数で 周回をまたいで保持(プレイヤーごと) にチェック |
| 見つけた実績とロック中の実績を見せる | プレイヤー画面 → コレクション テンプレート、または ロック解除の条件 を付けたリストの部品 |
| 数を数える | 計算式 len(Achievements) の数値変数 |
| 独自のパネル | リストを読む画面のコード(上の「コードで作る場合」) |
