Skip to content

昼夜サイクル

自動進行する時間システムを構築しましょう — 3ターンごとに時間が進みます(朝 → 昼 → 夕方 → 夜 → 朝)。異なる時間帯ごとに異なるロアエントリとバックグラウンドミュージックが有効になり、AIの執筆雰囲気をそれに合わせて変化させます。プレイヤーは何もする必要がありません — 時間はただ流れていきます。


これから作るもの

チャット内に組み込まれた昼夜サイクルシステム:

  • 自動カウント — 各対話ターンで内部カウンタが1ずつ増加。3ターン目で時間が1時間帯進む
  • 4つの時間帯 — 朝 → 昼 → 夕方 → 夜 → 朝(以降繰り返し)
  • 雰囲気の切り替え — 各時間帯に独自のロアエントリがあり、その時間帯の光、温度、NPCの行動などを記述。時間帯が変わると古いエントリが無効化され、新しいエントリが有効になる
  • BGM切り替え — 朝は鳥のさえずり、夜はコオロギとカエルに切り替わる。遷移はクロスフェードで突然のカットがない
  • 時間バッジ — チャットの最後のメッセージに小さなアイコン(☀️🌤️🌅🌙)が表示され、プレイヤーは常に時間を把握できる

仕組み

システム全体を要約すると:カウンタが毎ターン+1 → カウンタが3に達する → 時間帯を切り替え → カウンタをリセット → エントリとミュージックをトグル

プレイヤーがメッセージ送信 → AI返信 → ターン終了
  → 「毎ターン+1」ビヘイビアが発火:turn_counter が 0 から 1 へ
  → 次ターン:turn_counter が 1 から 2 へ
  → 次ターン:turn_counter が 2 から 3 へ
  → 「変数閾値クロス」ビヘイビアが発火:turn_counter が 2 を超える
  → アクション実行:time_period を次の時間帯に設定、turn_counter を 0 にリセット
  → 古い時間帯エントリ無効、新しい時間帯エントリ有効
  → 新しい時間帯のBGMにクロスフェード
  → Root Componentが変数を読んで時間バッジを更新

これを実装する方法は2つあります。同じ結果、異なる思考モデル:

アプローチ使用トリガービヘイビア数適している人
アプローチA:毎ターン+1 + 変数クロスevery-turn + variable-crossed2基礎メカニクスを理解したい人
アプローチB:Nターンごとに直接発火turn-count(everyNTurns=3)1とにかく動かしたい人

このレシピではアプローチAを教えます(より汎用的で、ビヘイビアの連鎖を理解するのに役立ちます)。アプローチBは最後に簡単にカバーします。


ステップバイステップ

ステップ1:変数の作成

2つの変数が必要です — 現在の時間帯を追跡するもの、カウンタとして機能するもの。

エディタ → サイドバー → Variables タブ → 各々「Add Variable」をクリック

変数1:現在の時間帯

フィールド理由
NameCurrent Time Period自分用の識別名
IDtime_periodビヘイビアとRoot Componentがこれを読み書き
TypeString値がテキスト("Morning""Noon""Evening""Night")だから
Default ValueMorning新規セッションは朝から開始
CategoryCustom時間システム専用カテゴリ
Behavior RulesDo not modify this variable. It is controlled automatically by the day-night cycle system. Its current value represents the in-game time period.AIに時間を自分で変更しないよう伝える — ビヘイビアのみ可能

変数2:ターンカウンタ

フィールド理由
NameTurn Counter自分用の識別名
IDturn_counter各ターン増加、3でリセット
TypeNumber算術が必要
Default Value00からカウント開始
CategoryCustom時間システム専用カテゴリ
Behavior RulesDo not modify this variable. It is controlled automatically by the day-night cycle system.AIによる改ざんを防ぐ

なぜ3ターンごとに直接発火する代わりにカウンタを使うのか?

カウンタ + 変数クロスのアプローチはより柔軟です。後で「昼は3ターン、夜は5ターン」が欲しくなった場合、ビヘイビアに条件チェックを追加するだけです。turn-countトリガーはよりシンプルですが適応性が低いです。どちらのアプローチにも強みがあります。ニーズに合うものを選んでください。


ステップ2:4つの時間帯ロアエントリを作成

各時間帯にその時間帯の雰囲気を記述するロアエントリが必要です。デフォルトで有効なのは「朝」のみで、他の3つは無効から開始します。

エディタ → Lore タブ → エントリを1つずつ作成

エントリ1:朝の雰囲気

フィールド理由
NameMorning Atmosphere自分用の識別名
SectionPresetsプリセットエントリは毎回AIに送信される
EnabledYes(トグルオン)ゲームは朝から始まるので、これがデフォルトでオン

内容:

[Current Time Period: Morning]
It is early morning. Reflect the following atmosphere when describing the scene:
- Soft morning light spills in from the east; the air is fresh and cool
- Dewdrops cling to blades of grass and flower petals, refracting tiny glints of light
- Birds sing in the branches; a rooster crows in the distance
- NPCs are just waking up, shops are opening one by one, foot traffic is picking up
- The overall mood is peaceful and full of hope

エントリ2:昼の雰囲気

フィールド理由
NameNoon Atmosphere自分用の識別名
SectionPresetsプリセットセクション
EnabledNo(トグルオフ)時間帯が切り替わったらビヘイビアが有効化

内容:

[Current Time Period: Noon]
It is midday. Reflect the following atmosphere when describing the scene:
- The sun beats down directly overhead; the light is searing and bright, the ground reflecting a blinding white glare
- The air is stifling; distant scenery shimmers and warps in the heat haze
- Most people have retreated to the shade to rest; the streets are quieter than morning
- Taverns and eateries are at their busiest, the smell of food drifting through the air
- The overall mood is languid and sweltering

エントリ3:夕方の雰囲気

フィールド理由
NameEvening Atmosphere自分用の識別名
SectionPresetsプリセットセクション
EnabledNo(トグルオフ)ビヘイビアが有効化

内容:

[Current Time Period: Evening]
It is dusk. Reflect the following atmosphere when describing the scene:
- The setting sun paints the sky in shades of orange-red and purple, clouds rimmed with gold
- Long shadows stretch from buildings and trees
- Flocks of birds sweep across the sky heading home; wisps of cooking smoke rise from rooftops
- NPCs are wrapping up for the day, heading home; children chase each other through the streets
- The overall mood is warm, nostalgic, tinged with a gentle melancholy

エントリ4:夜の雰囲気

フィールド理由
NameNight Atmosphere自分用の識別名
SectionPresetsプリセットセクション
EnabledNo(トグルオフ)ビヘイビアが有効化

内容:

[Current Time Period: Night]
It is deep night. Reflect the following atmosphere when describing the scene:
- Moonlight and starlight are the only natural sources of illumination, casting a silvery glow over everything
- Most buildings have gone dark; the occasional window glows with dim candlelight
- A cool night breeze carries the chorus of crickets and frogs
- The streets are nearly deserted; night-watch guards pace slowly by, torches in hand
- Danger may lurk in the shadows — wild beasts, thieves, or something stranger still
- The overall mood is mysterious, hushed, and laced with hidden peril

なぜデフォルトで「朝」だけが有効なのか? ゲームが朝から始まるからです。4つのエントリすべてが同時に有効だと、AIは朝、昼、夕方、夜の記述を同時に受け取り、どれに従うべきかわかりません。一度に1つだけ有効にすることで、AIを正しい雰囲気に固定し続けます。


ステップ3:(オプション)時間帯のBGMをアップロード

各時間帯に独自のバックグラウンドミュージックが欲しい場合は、まずオーディオファイルをアップロードします。

エディタ → Audio タブ → トラックを追加

トラックID名前タイプループフェードインフェードアウト
bgm_morningMorning ThemeBGMYes2s2s
bgm_noonAfternoon ThemeBGMYes2s2s
bgm_eveningDusk ThemeBGMYes2s2s
bgm_nightNight ThemeBGMYes2s2s

オーディオファイルがない? このステップをスキップ。昼夜サイクルの核はロアエントリの切り替えです — BGMは素敵なボーナス。後でいつでも追加できます。

BGMプレイリストで、autoPlaytrueに設定し、デフォルトをbgm_morningに。後で時間帯が切り替わるとき、ビヘイビアがcrossfadeアクションを使ってスムーズにトラックを遷移させます。


ステップ4:ビヘイビアの作成

これがシステムの心臓部です。2つのビヘイビアが必要 — いえ実は6つです。読み進めてください。

エディタ → Behaviors タブ → ビヘイビアを1つずつ追加

ビヘイビア1:毎ターンカウント

これは非常にシンプル — 各対話ターン後、カウンタが1ずつ増加。

WHEN(チェックタイミング):

フィールド理由
Trigger typeEvery turn各プレイヤー・AI交換後に自動的に発火

DO(実行内容):

Action type設定効果
Modify variableturn_counter1を加算カウンタ+1

唯一のアクションです。条件なし、追加設定なし。毎ターン忠実に1を加算します。

なぜここで「3に達したか?」をチェックしないのか? ビヘイビアシステムの設計哲学は、1つのビヘイビアに1つの仕事だからです。カウンタを増加させるのは1つのビヘイビアの仕事;3に達したかチェックするのは別のビヘイビアの仕事です。エンジンが自動的に連鎖します — カウンタが増加した後、値が閾値をクロスすれば、他のビヘイビアが発火します。


ビヘイビア2:時間帯を進める

このビヘイビアはカウンタが3に達したときに発火し、すべての切り替えロジックを実行します。

WHEN(チェックタイミング):

フィールド理由
Trigger typeVariable crossed thresholdturn_counterが閾値を超えたら発火
Variableturn_counter監視する変数
DirectionRises above値が閾値以下から閾値超に変わったら発火
Threshold2turn_counterが2から3になったとき発火(2を超える)

なぜ閾値が3ではなく2なのか? variable-crossedの「rises above」方向は、値が閾値以下から閾値超に変わる瞬間を検出します。turn_counterが2から3になるとき、「2を上回ってクロス」 — つまり<=2から>2へ。閾値を3に設定すると、turn_counterが3から4にならないと発火しません。それは望んでいることではありません。

DO(実行内容):

このビヘイビアは多くのことをする必要があります。これらのアクションを順番に追加:

#Action type設定効果
1Modify variableturn_counter0に設定次の3ターンカウントダウンのためにカウンタをリセット
2Disable lore entryMorning Atmosphereすべての時間帯エントリをオフ
3Disable lore entryNoon Atmosphereすべてオフ
4Disable lore entryEvening Atmosphereすべてオフ
5Disable lore entryNight Atmosphereすべてオフ

待って — それは4つすべてをオフにします。どれを有効にするか、どうやって知るの?

良い質問。ここで分岐のためのONLY IF条件が登場します。しかし1つのビヘイビアは1セットのアクションしか持てません。そのため「時間帯を進める」を5つのビヘイビアに分割します:1つはカウンタリセットと全エントリ無効化、4つは対応する時間帯を有効化します。

整理し直しましょう:


完全なビヘイビアリスト(合計6つ):

ビヘイビア1:毎ターンカウント

(前述と同じ — 繰り返さない。)

ビヘイビア2:進行 — 朝 → 昼

WHEN:

フィールド
Trigger typeVariable crossed threshold
Variableturn_counter
DirectionRises above
Threshold2

ONLY IF:

変数演算子
time_periodequals (eq)Morning

DO:

#Action type設定効果
1Modify variableturn_counter0に設定カウンタリセット
2Modify variabletime_periodNoonに設定次の時間帯に進む
3Disable lore entryMorning Atmosphere古い時間帯エントリをオフ
4Enable lore entryNoon Atmosphere新しい時間帯エントリをオン
5Play musicbgm_noon、アクション:crossfade、期間 3s昼BGMにクロスフェード
6Tell AI内容:Time has advanced from Morning to Noon. Naturally reflect this time change in your upcoming descriptions.AIがスムーズに遷移できるようにする

ビヘイビア3:進行 — 昼 → 夕方

WHEN: ビヘイビア2と同じ(variable crossed threshold、turn_counter が 2 を超える)

ONLY IF:

変数演算子
time_periodequals (eq)Noon

DO:

#Action type設定効果
1Modify variableturn_counter0に設定カウンタリセット
2Modify variabletime_periodEveningに設定夕方に進む
3Disable lore entryNoon Atmosphere昼エントリをオフ
4Enable lore entryEvening Atmosphere夕方エントリをオン
5Play musicbgm_evening、アクション:crossfade、期間 3sBGMをクロスフェード
6Tell AI内容:Time has advanced from Noon to Evening. Naturally reflect this time change in your upcoming descriptions.AI遷移

ビヘイビア4:進行 — 夕方 → 夜

WHEN: 同上

ONLY IF:

変数演算子
time_periodequals (eq)Evening

DO:

#Action type設定効果
1Modify variableturn_counter0に設定カウンタリセット
2Modify variabletime_periodNightに設定夜に進む
3Disable lore entryEvening Atmosphere夕方エントリをオフ
4Enable lore entryNight Atmosphere夜エントリをオン
5Play musicbgm_night、アクション:crossfade、期間 3sBGMをクロスフェード
6Tell AI内容:Time has advanced from Evening to Night. Naturally reflect this time change in your upcoming descriptions.AI遷移

ビヘイビア5:進行 — 夜 → 朝

WHEN: 同上

ONLY IF:

変数演算子
time_periodequals (eq)Night

DO:

#Action type設定効果
1Modify variableturn_counter0に設定カウンタリセット
2Modify variabletime_periodMorningに設定朝に循環
3Disable lore entryNight Atmosphere夜エントリをオフ
4Enable lore entryMorning Atmosphere朝エントリをオン
5Play musicbgm_morning、アクション:crossfade、期間 3sBGMをクロスフェード
6Tell AI内容:Time has advanced from Night to Morning — a new day begins. Naturally reflect this time change in your upcoming descriptions.AI遷移

なぜ4つのビヘイビアに分割するのか? 各時間帯の遷移で異なるエントリを有効化し、異なるBGMを再生する必要があるからです。1つのビヘイビアは1セットの条件と1セットのアクションしか持てない — if-else分岐をサポートしない。そのため、異なるONLY IF条件を持つ4つのビヘイビアを使って分岐をシミュレートします:同じトリガーが発火する(カウンタが2を超える)と、エンジンはすべてをチェックしますが、time_periodが一致するものだけが実行されます。

ビヘイビア6:セッション初期化

このビヘイビアはセッション開始時に初期状態を設定し、新規セッションまたは再入場のために変数が正しい初期値であることを保証します。

WHEN:

フィールド理由
Trigger typeSession start (session-start)新規セッションが開始すると一度だけ自動的に発火

DO:

#Action type設定効果
1Modify variabletime_periodMorningに設定朝から始まることを保証
2Modify variableturn_counter0に設定ターンカウンタをリセット

なぜセッション初期化ビヘイビアが必要なのか? 変数のデフォルト値は最初に作成されたときにのみ有効です。プレイヤーがセッション中に終了して新しいセッションを開始した場合、変数は以前の値を保持している可能性があります(例:time_periodが「Night」のまま、turn_counterが2のまま)。セッション初期化ビヘイビアは、毎回新しいセッションが朝から、カウンタ0から始まることを保証します。

ビヘイビアの優先度

4つの進行ビヘイビアはすべてデフォルト優先度(0)のままで構いません。それらのONLY IF条件は相互排他的 — 現在の時間帯はそのうちの1つにしか一致しないため、衝突はありません。


ステップ5:Root Componentに時間バッジを追加

チャットの最後のメッセージに現在の時間帯のアイコンを表示し、プレイヤーが一目で時間を知れるようにします。

エディタ → Custom UI セクション → index.tsxを開く → 以下を貼り付け(デフォルトのreturn <Chat />を置き換え):

tsx
export default function MyWorld() {
  const api = useYumina();

  // ---- Read variable ----
  const timePeriod = String(api.variables.time_period || "Morning");

  // ---- Period icon and color map ----
  const timeConfig = {
    "Morning": { icon: "☀️", label: "Morning", color: "#fbbf24", bg: "rgba(251,191,36,0.15)" },
    "Noon": { icon: "🌤️", label: "Noon", color: "#f59e0b", bg: "rgba(245,158,11,0.15)" },
    "Evening": { icon: "🌅", label: "Evening", color: "#f97316", bg: "rgba(249,115,22,0.15)" },
    "Night": { icon: "🌙", label: "Night", color: "#818cf8", bg: "rgba(129,140,248,0.15)" },
  };

  const current = timeConfig[timePeriod] || timeConfig["Morning"];
  const msgs = api.messages || [];

  return (
    <Chat renderBubble={(msg) => {
      const isLastMsg = msg.messageIndex === msgs.length - 1;

      return (
        <div>
          {/* Render message text normally — contentHtml is already rendered HTML */}
          <div
            style={{ color: "#e2e8f0", lineHeight: 1.7 }}
            dangerouslySetInnerHTML={{ __html: msg.contentHtml }}
          />

          {/* Time badge — only on the last message */}
          {isLastMsg && (
            <div style={{
              display: "inline-flex",
              alignItems: "center",
              gap: "6px",
              marginTop: "12px",
              padding: "4px 12px",
              background: current.bg,
              border: `1px solid ${current.color}33`,
              borderRadius: "999px",
              fontSize: "13px",
              color: current.color,
              fontWeight: "600",
            }}>
              <span style={{ fontSize: "16px" }}>{current.icon}</span>
              <span>{current.label}</span>
            </div>
          )}
        </div>
      );
    }} />
  );
}

行ごとの解説:

  • api.variables.time_period — 現在の時間帯変数を読み取る
  • timeConfig — 各時間帯をアイコン、テキストラベル、色にマッピングするルックアップテーブル。ワールドのスタイルに合わせて色を変更してください
  • isLastMsg — バッジを最後のメッセージにのみ表示、各メッセージで表示しない
  • バッジはinline-flex + border-radius: 999pxでピル形状 — 控えめながらすぐに見える

各メッセージに時間を表示したい?

{isLastMsg && ...}チェックを削除し、バッジをreturnに直接配置します。チャットログのタイムスタンプのように、各メッセージにタイムスタンプが付きます。


ステップ6:保存してテスト

  1. エディタ上部のSaveをクリック
  2. Start Gameをクリックするか、ホームページに戻って新しいセッションを開始
  3. AIと普通にチャット。最初の2ターン、時間バッジは「☀️ Morning」を表示し何も変わらない
  4. ターン3後 — 時間が「🌤️ Noon」に進み、AIの次の返信が自然に時間変化を反映
  5. さらに3ターン — 「🌅 Evening」に進む
  6. さらに3ターン — 「🌙 Night」に進む。BGMを設定していれば、クロスフェードが聞こえるはず
  7. さらに3ターン — 「☀️ Morning」に戻り循環、新しい一日が始まる

うまく動かない場合:

症状想定される原因対処
時間が変わらない「毎ターンカウント」ビヘイビアが発火していないビヘイビア1のトリガーが「Every turn」に設定され、ビヘイビアが有効か確認
ターン3で切り替わらない閾値が間違っている「variable crossed threshold」の閾値が2(3ではない)、方向が「rises above」であることを確認
切り替え後エントリが変わらないエントリ名が一致しないビヘイビアの「Enable lore entry」/「Disable lore entry」アクションが正しいエントリ名を参照しているか確認
4つのビヘイビアすべてが一度に発火ONLY IF条件が欠落各進行ビヘイビアには現在のtime_period値を制限するONLY IF条件が必要
時間バッジが見えないRoot Componentの構文エラーCustom UIパネル下部のコンパイル状態を確認 — 緑の「OK」が表示されるべき
BGMが切り替わらないトラックID不一致またはオーディオがアップロードされていないビヘイビアのtrackIdがAudioタブのトラックIDと一致するか確認

アプローチB比較:turn-countトリガーを使う

アプローチAがビヘイビア数が多すぎると感じる場合、よりシンプルなアプローチBを使えます。

違い:

アプローチA(このレシピ)アプローチB
トリガーevery-turn + variable-crossedturn-count(everyNTurns=3)
turn_counter変数が必要はいいいえ
ビヘイビア数6(1カウント + 4進行 + 1オプショナル初期化)4(4進行)
柔軟性高(間隔を動的に調整可能)低(間隔はNに固定)
適している人動的な時間流速が必要なワールド固定リズムのワールド

アプローチBの実装方法:

turn_counter変数と「毎ターンカウント」ビヘイビアを削除。4つの進行ビヘイビアすべてのトリガーを次に変更:

フィールド
Trigger typeEvery N turns
everyNTurns3

それ以外(ONLY IF条件、DOアクション)はアプローチAとまったく同じです。turn-countトリガーが3ターンごとに自動的に発火 — 手動カウント不要。

turn-countトリガーの仕組み: エンジンが内部グローバルターン数を維持します。everyNTurns: 3を設定すると、エンジンはターン3、6、9、12などで自動的にビヘイビアを発火します。カウンタ変数を自分で管理する必要はありません。


クイックリファレンス

やりたいこと方法
毎ターン何かをするビヘイビアトリガー:「Every turn」(every-turn)
Nターンごとに何かをするビヘイビアトリガー:「Every N turns」(turn-count)、everyNTurnsを設定
変数が値をクロスするのを検出ビヘイビアトリガー:「Variable crossed threshold」(variable-crossed)、変数、方向、閾値を設定
ロアエントリを切り替えアクション:「Enable lore entry」/「Disable lore entry」
ミュージックをクロスフェードアクション:「Play music」、オペレーション:crossfade、フェード期間を設定
AIに何かが起こったことを知らせるアクション:「Tell AI」、一時的なシステム指示を書く
メッセージにステータスバッジを表示Root Componentの<Chat renderBubble>内で変数を読み、JSXでレンダリング
if-else分岐をシミュレート同じトリガーを共有する複数のビヘイビア + 異なるONLY IF条件

自分で試す — インポート可能なデモワールド

このJSONをダウンロードし、新規ワールドとしてインポートしてすべての動作を確認してください:

recipe-9-demo.json

インポート方法:

  1. Yumina → My WorldsCreate New World に移動
  2. エディタで More ActionsImport Package をクリック
  3. ダウンロードした.jsonファイルを選択
  4. 全変数、エントリ、ビヘイビア、Root Componentが事前設定された新規ワールドが作成されます
  5. 新規セッションを開始して試す

含まれるもの:

  • 2つの変数(time_periodが現在の時間帯を追跡、turn_counterはターンカウンタ)
  • 4つのロアエントリ(朝 / 昼 / 夕方 / 夜の雰囲気、デフォルトで朝のみ有効)
  • 6つのビヘイビア(1つの毎ターンカウント + 4つの時間帯進行 + 1つのセッション初期化)
  • Root Component(<Chat renderBubble>内の時間帯アイコンバッジ)
  • 4つのBGMトラック(独自のオーディオファイルをアップロードしてURLを置き換える必要あり)

これはRecipe #9です

このレシピはビヘイビアシステムの連鎖力を示しています — シンプルなカウンタ + 閾値トリガー + 条件分岐で、完全に自動の時間システムを構築できます。同じパターンが天候変化、季節サイクル、NPCの気分変化など、「リズムで自動的に変化する」あらゆるものに使えます。