Skip to content

ビヘイビアと自動化

プラットフォーム上のほとんどのワールドはルールを一切使っていません。それでまったく構いません。ルールは少数派のツールです — クリエイターがそれを手にするのは、AIに一貫性が期待できない、ごく特定のジョブが手元にあるときです。

このガイドではルールが価値を持つ場面、得意なこと、構築方法を解説します。トリガー、条件、アクションの基本については はじめに:自動化 を参照してください。


ルールが価値を持つ場合(持たない場合)

ルールに関して新規クリエイターが最もよくやるミスは、過剰設計です。エディタのビヘイビアセクションを見て「何でも自動化すべき」と思ってしまいます。そして30個のルールを構築し、よく書かれたエントリがすでに扱っていることを複製してしまい、ワールドが生き生きとせず機械的になります。

ルールは精密性のためにあります。 AIの不一致が体験を壊すような問題を解決します。

問題なぜルールで解決するか
「親密度がちょうど75になったらプレイヤーに通知すべき」AIは正確な数字を知らない — エンジンは知っている
「アリーナに入ったらバトルミュージックに切り替え」AIは半分はオーディオディレクティブを忘れる
「3ターンごとに空腹度を増加」AIは時々ターン2でやり、時々完全に忘れる
「HPが0になった瞬間にデス画面が出るべき」AIが一度でも間違えると致命的

エントリは物語のためにあります。 柔軟性とニュアンスが重要な問題を解決します。

問題なぜエントリで解決するか
「信頼が育つにつれてNPCの話し方を変える」条件付きエントリはAIに行動指針を与え、硬直したスクリプトを与えない
「プレイヤーがロケーションを訪れたら伝承を明かす」キーワードトリガーのエントリはAIのコンテキストに自然に流れ込む
「ダンジョンに入ったらトーンを変える」エントリは雰囲気を描写する。ルールはディレクティブを注入するだけ

経験則: ルールの inject-directive アクションに物語テキストの段落を書いているなら、おそらくエントリを書くべきです。ルールはスイッチとダイヤル。エントリは実際のコンテンツです。

Sakura Seasonがどう両方を使っているか

Sakura Seasonはルールとエントリが共に働く最良の例です。9つのルールがあり — すべて同じ基本ジョブを行っています:親密度しきい値を監視。

エントリ は各ヒロインが異なる親密度レベル(警戒、打ち解け、弱さを見せる)でどう振る舞うかを描写します。ルール は精確な瞬間を扱います:25での通知(「You've caught Hina's attention...」のような)、50で矛盾するプッシュ・プル行動を書くようAIに伝えるディレクティブの注入、75での告白アークをトリガーする実績トースト。

エントリが重い仕事をします。ルールはマイルストーンをきっかり正しい瞬間に着地させます。


トリガー型を深く

トリガーはエンジンが いつ このビヘイビアをチェックするかを決定します。異なる種類の目覚まし時計のようなものと思ってください。

実際によく使うもの

変数がしきい値を超えるvariable-crossed) — 最も人気のトリガーで理由があります。number変数が特定の線を超える その瞬間 に発火します。

これは毎ターン「healthは20未満か?」をチェックするのとは違います。crossedトリガーは値が実際にしきい値を 横切る ときに 一度だけ 発火します。healthが既に10で10のままなら、再発火しません。

設定するのは3つ:どの変数、どのしきい値、どの方向(rises-above または drops-below)。

Wandering Diaryはこれを3つ使ってリージョン切り替えを実装:distance 変数が50を超えると郡へ入り、150で山、200で省都。各しきい値が新しい region 変数をセットし通知を表示します。

状態変化state-change) — 最も広いトリガー。任意の 変数が変わるたびに発火します。条件と組み合わせて関心事を絞り込みましょう。

これはしきい値の超過ではなく、変数が特定の値を持つことに反応したいときに使います。例:「状態が変化するたび、locationが dark_forest かをチェックし、そうなら不気味な音楽を再生」。何が変化を引き起こしたとしても、ルールが再チェックするので、ロケーション変化を見逃しません。

Nターンごとturn-count) — スケジュールで発火します。everyNTurns: 3 でターン3、6、9、12…に発火。atTurn: 10 で特定ターンの単発。

サバイバルメカニクス(空腹度の増加)、ペース調整イベント(ターン20で時間切れ警告)、定期リマインダーに適します。

毎ターンevery-turn) — プレイヤー/AIの往復ごとに発火します。慎重に使ってください — 毎ターン何か可視のことを行うルールはプレイヤーを苛立たせます。ほとんどのターンをフィルタする条件付きで使うか、サイレントなバックグラウンド処理用にしましょう。

セッション開始session-start) — 新会話の開始時に1度だけ発火。初期化に良い:開始値の設定、ようこそメッセージ表示、オープニングミュージック再生。

あまり使われないトリガー

プレイヤーキーワードkeyword) — プレイヤーのメッセージが特定のワードを含むと発火。ロアブックのキーワードと同じマッチオプション:オプションのwhole-wordマッチング、正規表現(キーワードが /.../flags のとき)、セカンダリキーワードフィルタ(AND_ANY、AND_ALL、NOT_ANY、NOT_ALL)。

AIキーワードai-keyword) — 上と同じだがAIの応答をスキャン。AIが書いたことに反応するのに有用、例「AIが 'battle begins' と書いたら音楽切り替え」。

手動manual) — カスタムコンポーネントから api.executeAction() で明示的に呼ばれた時のみ発火。ボタン押下でゲームロジックを起動するカスタムUIのワールド用。

アクションaction) — 特定のカスタムアクションボタンが押されたときに発火。

一定間隔でのスケジューリング

ビヘイビアセクションに実時間のタイマーはありません——ペースは秒ではなくターンで測ります。周期的なものには N ターンごと トリガーを使ってください:第 N、2N、3N…… ターンで発火します(5 に設定すると第 5、10、15 ターンで発火)。生存値の減少、維持コスト、繰り返しのリマインダー——タイマーが担うはずの仕事はこれでカバーできます。


条件:ONLY IFチェック

ルールはエントリと同じ条件システムを使います — 同じ7演算子(eqneqgtgteltltecontains)と同じAll/Any結合ロジック。完全な演算子リファレンスは 優れたエントリの書き方:状態駆動エントリ を参照してください。

条件を空のままにすると、ルールはトリガーがマッチするたびに発火します。

ある変数を別の変数と比べる

デフォルトでは、条件は変数を固定の数値や単語と比べます——「好感度 ≥ 50」。しかし右辺には 定数 / 変数 トグルがあります。変数 に切り替えると、条件は2つのライブ変数を比較するようになります:

  • 好感度 > 警戒心 —— 好感度が今まさに警戒心を上回っている間だけ発火
  • 所持金 >= 価格 —— 価格をハードコードせずに「買えるか」をチェック

しきい値そのものが固定ではなく、ゲームとともに動く場合にこれを使います。同じ仕組みにあと2つ:

  • 左辺は JSON 変数へのドットパスを受け付けます:インベントリ.所持金 >= 100
  • contains は部分文字列に加えて 配列メンバーシップ にもマッチします。フラグ がその要素を含むリストなら フラグ contains "王に会った" は真になります。

アクション型:ルールができること

条件が通ると、エンジンはアクションを順に実行します。1つのルールに複数アクションを含められます — ここがルールが強力になる場所です。

変数を修正

ゲーム状態変数を直接変更。9操作:setaddsubtractmultiplytoggleappendmergepushdelete

最も一般的:set(値を上書き)、add/subtract(数値の増減)、toggle(ブール反転)。

オペランドにも同じ 定数 / 変数 トグルがあります。変数 に切り替えると、別の変数の現在値をその操作に流し込めます——生命 -= 力スコア += コンボ財布 += 日収。エンジンはルールが発火した瞬間に参照先の変数を読むので、計算は常にライブ値を使い、手で同期する数値は要りません。

ディレクティブを注入

AIのプロンプトに一時的な指示を追加。これはおそらく最も強力なアクションです。なぜならAIが 指示されたこと を変えるため、物語の方向全体が変わるからです。

ユニークなID(後で削除できるよう)、指示テキスト、プロンプト内の配置(topbefore_charafter_charbottomdepthauto)を指定します。

デフォルトでは注入されたディレクティブはターン間で持続します(persistent: true)。duration を設定してNターン後に自動失効させることもできます。

Sakura Seasonは各ヒロインの親密度50でこれを使います。Rinが50に達するとルールが注入:「Rinの親密度が深い段階に入った。氷が割れ始める。委員会で不必要なことを言い、屋上で読んでいた本について無意識に意見を共有し、その後突然黙る。」 AIはそれ以降毎ターンこれを読み、その描写を自然にシフトします。

ディレクティブを削除

以前に注入したディレクティブを削除。注入時の同じ directiveId で参照します。

コンテキストを送信

AIに不可視のメッセージを送り応答をトリガー。プレイヤーはこのメッセージを見ませんが、AIはそれを読み、それに応じて応答します。物語のビートを強制するのに便利:「モンスター登場! ランダムエンカウントを描写」。

エントリをトグル

ロアブックエントリをIDで有効/無効にします。toggle-entryenabled: true をアクティブにするルールは、適切な瞬間に隠れた伝承を明かすことができます。

ルールをトグル

別のビヘイビアを有効/無効。連鎖を構築する鍵:ルールAがダンジョンに入ったときにアクティブになり、ルールB(毎ターンのモンスターエンカウンタ)を有効化。ルールCがダンジョンから出るとアクティブになりルールBを無効化。

プレイヤーに通知

トースト通知をポップアップ。4スタイル:

スタイル見た目適した用途
info中立的な更新(「新リージョンに入った」)
achievementマイルストーンとアンロック
warning注意(「補給が尽きてきた」)
danger重大警告(「あなたは倒れた」)

オーディオを再生

BGMと効果音を制御。trackId(オーディオ設定のトラックに一致)、actionplaystopcrossfadevolume)、オプションの volumefadeDuration を取ります。


公開ワールドの実例パターン

親密度しきい値(Sakura Season)

定番のユースケース。Sakura Seasonには3ヒロインに9ルールあり、それぞれ同じ3層パターンに従います。

親密度25で — 控えめなinfo通知。「Hinaの注意を引いたようだ...」と story_phase を "daily" にセット。単発(maxFireCount: 1)。

親密度50で — achievement通知。「Hinaがあなたを特別な存在として見始めている...」プラス矛盾するプッシュ・プル行動を描写するディレクティブを注入、story_phase を "deepening" にセット。単発。

親密度75で — クライマックストリガー。Achievement通知、告白シーンをアレンジするディレクティブ、story_phase を "climax"。単発。

パターンに注目:すべてのルールは variable-crossed + rises-above を使い、ちょうど1回発火し、プレイヤー通知+AIディレクティブ+フェーズ変数更新を組み合わせます。3つのアクション型が連携して1つの意味ある瞬間を作ります。

リージョン切り替え(Wandering Diary)

Wandering Diaryはプレイヤーが旅するにつれて増加する distance 変数を追跡します。3つの variable-crossed ルールが距離50、150、200で region 変数を切り替え、それぞれ通知を表示:「ついに荒野を離れ郡の領域に入った」「郡を抜けて果てしない山脈が広がる」「遠くに省都の輪郭が現れる」。

これによりAIが距離を追跡したりリージョン境界を覚えたりすることなく、シームレスな旅の進行が生まれます。

デストリガー

Wandering Diaryとサバイバルキットテンプレートの両方が同じパターンを使います:variable-crossed で healthが1未満に落下、dangerスタイル通知。重要な詳細:

  • Priority 100 — 死は何より先に評価されるべき
  • maxFireCount: 1 — 死通知は1回だけ発火(ゼロを2度下回ることはないので大抵のワールドはこれを気にしませんが)
  • 時々 inject-directive と組み合わせ、AIにキャラクターの最期を描写するよう伝える

ダンジョン起動連鎖

RPGワールドの共通パターン:ルールAがダンジョンへの入場を聞き(キーワードトリガーまたは state-change + 条件)、toggle-rule でルールB(クールダウン付き every-turn のモンスターエンカウンタ)をアクティブ化。3つ目のルールが退出を聞きルールBを非アクティブ化。

これによりAIがダンジョン内かどうかを追跡することなくモンスターエンカウンタを特定エリアに限定できます。


エンジンがルールを処理する方法

各プレイヤーメッセージ、AI返信、状態変化の後、エンジンは1パスですべてのビヘイビアを実行:priorityでソート(高い順)、各々を順にチェック。各ビヘイビアについて尋ねる:有効か? トリガー型がこのイベントに合うか? トリガーの具体内容が合うか(キーワード発見、しきい値超過など)? 条件が通るか? クールダウン中か? max fire countを超えたか? すべて通ればアクションが収集される。すべてのビヘイビアがチェックされた後、収集アクションが順番に実行。それらが変数を変えると、エンジンは再評価する場合がある(無限ループ防止の深度制限あり)。

プロセス全体はプレイヤーに不可視 — 彼らは結果だけを見ます:通知、音楽の変化、変数更新。


ルール発火の制御

Priority(優先度)

数値が大きいほど先に評価されます。複数ルールが同時にトリガーされた場合、優先度が順序を決めます。

実用ガイド:デスチェックは100、ストーリーマイルストーンは50、雰囲気効果は10〜20。精密である必要はなく、重要なルールがあれば良いものより先に走るようにするだけです。

Cooldown(クールダウン)

発火後、ルールはこのターン数だけ眠ります。cooldownTurns: 5 の空腹警告は毎ターンプレイヤーを煩わせず、警告間に少なくとも5ターン空きます。

Max fire count(最大発火回数)

ルールは生涯で最大この回数まで発火可能。maxFireCount: 1 で単発イベント — 実績、初回チュートリアル、ストーリーマイルストーンに最適。

有効/無効状態

ルールはデフォルトで有効ですが、enabled: false を設定して別のルールが toggle-rule で有効化するまで休眠状態にすることもできます。これが上述したダンジョン起動パターンの基礎です。


よくあるミス

エントリで済むのにルールで過剰設計。 inject-directive アクション内に長い物語テキストを書いている自分に気付いたら、おそらく条件付きエントリが欲しいのです。ルールは1〜2文のガイダンスを注入。エントリは段落のコンテキストを提供。

variable-crossed のつもりで state-change を使う。 state-change任意の 変数が変わるたびに発火。「healthが20未満になったら通知」が欲しいなら variable-crossed を使ってください — 横切る瞬間に1回発火します。state-change + health < 20 をチェックする条件だと、healthが20未満の間、その後の状態変化のたびに 発火し、それは恐らく望むものではないでしょう。

頻繁なトリガーでクールダウンを忘れる。 クールダウンなしの every-turn ルールは毎ターン発火します。通知を表示するならプレイヤーはスパムされます。常に問いましょう:「これをプレイヤーが実際にどれだけの頻度で見るべきか?」

3つで済むワールドに30個のルールを作る。 Sakura Seasonを見てください:9ルール、3ヒロイン、各3しきい値。深いメカニクスを持つワールドです。ほとんどのワールドはもっと少なくて済み、多くの人気作は0で出荷されます。エントリと変数から始めましょう。AIが特定のことに一貫しないと気付いたときだけルールを追加してください。

しきい値をテストしない。 health < 10 でルールが発火するが、AIが実際にhealthをそこまで下げない(「healthが30未満なら負傷したと描写」とエントリで指示しているため)なら、ルールは決してトリガーしません。しきい値がワールドの実際の動作と整合することを確認してください。


関連項目

完全なルールスキーマと評価パイプライン → World Spec:ルールとリアクション