v
Skip to content

オーディオデザインガイド ​

カードに音を付けるためのパターン集です。勝手に流れ出す BGM、場面に合わせて変わる音楽、キーワードで鳴る効果音、環境音のループ、物語に合わせて AI が選ぶ音楽、自分で書いたインターフェースのコードで作るジュークボックス。必要なものだけ選んでください。組み合わせても使えます。


概要 ​

音を操作できる場所はいくつかあります。

方法設定する場所どんなものか
デフォルトプレイリストオーディオ ページ → BGM設定プレイヤーが入ると音楽が始まり、用意した曲を順に流します
条件付きBGMオーディオ ページ → BGM設定 → 条件付きBGM変数、キーワード、ターン数、セッション開始に応じて曲を切り替えます。ビヘイビアは要りません
AI に選ばせるトラックの この曲を AI に流させる / この効果音を AI に鳴らさせる合う場面を一行書いておくと、物語がそれに合ったときに AI が流します
ビヘイビア効果の 音楽を再生、効果音を再生、オーディオを停止ほかの処理(変数を変える、ロアを開く、短いジングルを鳴らす)と並べて音を扱います
プレイヤー画面のボタン手順の 音声を再生 / 音声を停止曲を再生・停止するボタンをコードなしで作れます
インターフェースのコードapi.playAudio() / api.stopAudio()ジュークボックスのように、すべてを自分で制御できます

オーディオ ページは、キャンバスのオーディオブロックから開きます(カードにまだなければ、追加できるもの の列で + オーディオ を押します)。パネル → オーディオ からも開けます。


パターン1:自動で流れる BGM ​

ステップ1:トラックを追加する ​

オーディオ ページで トラックを追加 を押し、次のように入力します。

項目値理由
タイトルMain Theme自分で見分けるため
オーディオソース.mp3 か .ogg をアップロード、または アセットを参照
トラックタイプBGM背景音楽
ループ再生オンBGM はふつうループさせます
デフォルト音量0.7効果音や環境音が入る余地を残します
フェードイン(秒)2いきなり鳴らず、少しずつ入ってきます

トラックにはそれぞれ編集できない 音声トラック ID が付きます。トラック名を変えても ID は変わりません。必要になるのはインターフェースのコードを書くときだけです(横に ID をコピー があります)。

曲を増やしたいときは、探索、戦闘、町など、トラックを追加していきます。

ステップ2:デフォルトプレイリストを設定する ​

BGM設定(プレイリスト + トリガールール)を押します。

項目値理由
デフォルトプレイリストMain Theme(とほかの BGM トラック)を選ぶリストの曲が順番に流れます
再生モードループ、シャッフル、順番 のどれかループはリストを順に繰り返し、シャッフルは順番をランダムにします
自動再生オンプレイヤーがカードに入ると音楽が始まります
最初のメッセージを待つオフ(またはオン)オンにすると、プレイヤーが最初のメッセージを送るまで音楽を待ちます
トラック間の間隔(秒)0(または 2)0 なら曲と曲が切れ目なくつながります

結果 ​

プレイヤーがカードを開く → 音楽が 2 秒かけてフェードインする → 曲が終わると次の曲が始まる → 最後の曲のあとはリストの最初に戻る。

曲が 1 つだけなら

ループ再生 をオンにして、プレイリストにその曲だけを入れます。


パターン2:変数に合わせて変わる音楽 ​

これから作るもの ​

プレイヤーが村からダンジョンに移ると、村の音楽がフェードアウトしてダンジョンの音楽がフェードインします。体力が 20 を下回ると緊迫した音楽に切り替わり、回復すると元の音楽に戻ります。ビヘイビアはひとつも要りません。

しくみ ​

トリガーが 変数条件 の 条件付きBGM ルールは、値が変わるたびにチェックされます。条件を満たせばそのルールの曲を流し、満たさなくなったら 終了時 の設定で次に流すものが決まります。デフォルトプレイリストに戻る、前のトラックに戻る、または特定のトラックです。

ステップバイステップ ​

文字の変数 Location(初期値 village)と、トラック Village、Dungeon を用意しておきます。そのうえで BGM設定 → 条件付きBGM → 条件付きルールを追加 を押します。

項目値理由
トリガー変数条件変数の値で決まります
条件Location が dungeon
再生Dungeon
優先度10複数のルールが同時に当てはまったときは、数字の大きいほうが勝ちます
フェードイン(秒)2新しい曲がフェードインします
フェードアウト(秒)2古い曲がフェードアウトします
前のBGMを停止オン村の音楽を下で鳴らし続けず、止めます
終了時デフォルトプレイリストに戻るプレイヤーがダンジョンを出たら村の音楽に戻ります

体力が低いとき用に、もうひとつルールを作ります。

項目値
トリガー変数条件
条件体力が 20 より小さい
再生Crisis
優先度20(場所のルールより大きいので、ダンジョンの中でもこちらが勝ちます)
前のBGMを停止オン
終了時前のトラックに戻る
プレイヤーが探索中で、プレイリストが流れている
  → 体力が 30 から 15 に下がる
  → ピンチのルールが当てはまり、プレイリストがフェードアウトして Crisis がフェードイン
プレイヤーが薬を飲み、体力が 35 に戻る
  → ルールが当てはまらなくなり、「終了時」の設定で前に流れていた曲に戻る

条件を複数にする

1 つのルールに条件をいくつも付けられます。「体力が 20 未満 かつ Location が dungeon」なら すべての条件を満たす、どちらか一方でよければ いずれかの条件を満たす を選びます。

Location は誰が変えるの?

変数を変えるものなら何でも構いません。AI(変数のビヘイビアルールに従って)、プレイヤー画面のボタン(変数を変える)、ビヘイビアのどれでも。音楽のルールは、どうやって変わったかは気にしません。ボタンの作り方はマップとシーン移動で紹介しています。


パターン3:キーワードで鳴る効果音 ​

これから作るもの ​

AI が「explosion」と書いたら爆発音、プレイヤーが「open the door」と言ったらドアのきしむ音。オーディオ ページだけで設定でき、ビヘイビアは使いません。

ステップ1:SFX トラックを追加する ​

項目爆発ドア
タイトルExplosionDoor Open
トラックタイプSFXSFX
ループ再生オフオフ
デフォルト音量0.90.8

ステップ2:条件付きBGMルールを追加する ​

名前は「BGM」ですが、条件付きBGMのルールは SFX を含むどのタイプのトラックでも流せます。

ルール:AI が「explosion」と言う

項目値
トリガーAIキーワード
キーワードexplosion、blast、detonate(1 つずつ入力して Enter。どれか 1 つで発動します)
再生Explosion
前のBGMを停止オフ。効果音の下で音楽が鳴り続けます

ルール:プレイヤーが「open the door」と言う

項目値
トリガープレイヤーキーワード
キーワードopen the door、push the door
再生Door Open
前のBGMを停止オフ

単語単位で一致 をオンにすると、「blast」が「blasted」の中の一部として一致しなくなります。どちらにも反応させたいならオフのままにします。


パターン4:環境音のループ ​

これから作るもの ​

雨、風、酒場のざわめきなどを、音楽の下で小さく鳴らします。

しくみ ​

環境音 は 3 つめのトラックタイプです。BGM と同時に鳴るので、BGM 1 曲と環境音 1 つを重ねられます。ループさせて、音量は小さめにしておきます。

ステップ1:環境音のトラックを追加する ​

項目値
タイトルForest
トラックタイプ環境音
ループ再生オン
デフォルト音量0.3(音楽より小さく)
フェードイン(秒)3
フェードアウト(秒)3

ステップ2:鳴らしたい場所で鳴らす ​

パターン2と同じように条件付きBGMルールを使います。変数条件 で Location が forest、再生は Forest、終了時 は デフォルトプレイリストに戻る です。

環境音のルールでは 前のBGMを停止 をオフにしてください。環境音は音楽の上に重ねるものなので、オンのままだと雨の音が始まった瞬間に音楽が止まってしまいます。

すでに場面の切り替えを担当しているビヘイビアがあるなら、そこで鳴らすこともできます。環境音のトラックを 効果音を再生 か 音楽を再生 で鳴らし、古いものは オーディオを停止 で止めます。

音量の目安

BGM は 0.5〜0.7、環境音は 0.2〜0.4、効果音は 0.7〜1.0 くらい。音量をずらしておくと、3 つの層がお互いをかき消しません。


パターン5:AI に音楽を選ばせる ​

これから作るもの ​

物語が酒場に入ればにぎやかな酒場の音楽、戦いが始まれば戦闘曲、誰かが剣を抜けば刃のぶつかる音。場面ごとにルールを書かなくても、こうした切り替えができます。

しくみ ​

トラックを開いて、この曲を AI に流させる(BGM トラック)か この効果音を AI に鳴らさせる(SFX トラック)を書きます。環境音のトラックはこの方法では選ばれないので、ルールで動かしてください(パターン4)。

トラック項目書く内容
Tavern(BGM)いつ流すかにぎやかで楽しい:酒場、市場、お祭り
Battle(BGM)いつ流すか戦いが始まる、または追いかけっこが始まる
Sword Clash(SFX)何が起きたら一度鳴らすか誰かが刃を抜く、または剣と剣がぶつかる

一行書いたトラックには オン:物語が合ったとき AI がこの曲を流します と表示されます。返信のたびに、カードが物語の内容をそれぞれの一行と照らし合わせ、音楽を切り替えたり効果音を鳴らしたりします。これは スマートトラッキング(カードの設定 にあります)の一部として動くので、プレイヤーがどのモデルを使っていても同じように働きます。一行を空にしておけば、そのトラックはプレイリストとルールだけで流れます。

一行を書いたトラックが 1 つでもあると、BGM設定 の欄に、AI の選曲とルールの兼ね合いについての質問がいくつか出てきます。どれも実際に起こりうるときだけ表示されます。

  • AI が曲を変えたいのに、条件ルールが自分の曲を流しているとき:ルール優先(ルールの曲が鳴り続け、AI は待つ)か AI 優先 か
  • AI が選んだ曲が終わったら:AI が曲を変えるかプレイリストに戻すまでループするか、一度だけ流してデフォルトプレイリストに戻るか
  • AI が効果音を鳴らす間は BGM を下げ、終わったら戻す

AI に触らせないトラック ​

トラックの AI による操作を許可 をオフにすると、AI はそのトラックを再生も停止も変更もできなくなります。プレイリスト、ルール、ビヘイビア、インターフェースのコードからは今までどおり操作できます。メニュー画面の曲や、コードで管理しているトラックに使います。

オーディオディレクティブ ​

物語を書く AI は、返信の中にオーディオディレクティブを直接書くこともできます。AI が操作してよいトラックの一覧(ID、タイプ、タイトル)とディレクティブの書き方は、エンジンが自分で AI に渡すので、一覧を書いたロアエントリを用意する必要はありません。ディレクティブはプレイヤーに表示される前に本文から取り除かれます。

酒場の重い扉を押し開けると、暖かい空気が顔に当たった。[audio: <酒場のトラック ID> crossfade 2]
ディレクティブ効果
[audio: trackId play]再生(トラック自身の フェードイン で)
[audio: trackId stop]停止(トラック自身の フェードアウト で)
[audio: trackId crossfade 2]AI が操作しているほかの BGM を止め、この曲を 2 秒かけてフェードイン
[audio: trackId volume 0.5]音量を変える
[audio: trackId play chain:nextTrackId]この曲が終わったら次の曲を始める

chain はイントロに向いています。角笛の音が鳴り終わったら、そのまま戦闘曲につなげる、といった使い方です。

AI はいつもディレクティブを書いてくれるとは限らず、長いチャットではとくに忘れがちです。確実なのは上の一行(いつ流すか)と条件付きBGMルールで、ディレクティブはおまけと考えてください。


パターン6:音を鳴らすボタン ​

コードなし:プレイヤー画面のボタン ​

プレイヤー画面 で ボタン を選び、押したとき、順番に に 音声を再生(トラックを選ぶ)か 音声を停止(トラック 1 つ、または すべて停止)を追加します。ビヘイビアの効果 音楽を再生、効果音を再生、オーディオを停止 でもキャンバスから同じことができ、ボタンから ビヘイビアを動かす でそのビヘイビアを実行できます。

カスタムコードの方法:ジュークボックス ​

useYumina() から、インターフェースのコードで次のオーディオ関数が使えます(時間の単位はすべて 秒 です)。

  • api.playAudio(trackId, opts):トラックを再生します。opts には volume(0〜1)、fadeDuration、chainTo、maxDuration、duckBgm、loop(その回だけトラック自身のループ設定を上書き)を入れられます
  • api.stopAudio(trackId?, fadeDuration?):トラックを 1 つ止めます。ID を省くとすべて止まります。再生位置は破棄されるので、続きから再開したいときは pauseAudio を使います
  • api.pauseAudio(trackId) / api.resumeAudio(trackId):その位置で一時停止・再開します
  • api.onAudioEnded(cb):ループしないトラックが終わると cb(trackId) を呼びます。戻り値は購読を解除する関数です

playAudio はほかの音楽を自動では止めません。BGM を切り替えるときは、先にほかの曲を止めてください。

オーディオ ページで各トラックの 音声トラック ID をコピーしたら、パネル → フロントエンドコード → index.tsx で、デフォルトの return <Chat /> を置き換えます。

tsx
export default function MyWorld() {
  const api = useYumina();
  const msgs = api.messages || [];

  // Paste the Track IDs from the Audio page
  const tracks = [
    { id: "PASTE-JAZZ-TRACK-ID", label: "Jazz", color: "#7c3aed" },
    { id: "PASTE-ROCK-TRACK-ID", label: "Rock", color: "#dc2626" },
    { id: "PASTE-CLASSICAL-TRACK-ID", label: "Classical", color: "#0891b2" },
  ];
  const [nowPlaying, setNowPlaying] = React.useState("");

  const play = (t) => {
    // Fade out the other jukebox tracks, then fade this one in
    tracks.forEach((other) => {
      if (other.id !== t.id) api.stopAudio(other.id, 1.5);
    });
    api.playAudio(t.id, { fadeDuration: 1.5 });
    setNowPlaying(t.id);
  };

  const stop = () => {
    api.stopAudio();
    setNowPlaying("");
  };

  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: "12px",
              padding: "12px",
              background: "rgba(30,41,59,0.5)",
              borderRadius: "8px",
              border: "1px solid #334155",
            }}>
              <div style={{ fontSize: "12px", color: "#94a3b8", marginBottom: "8px" }}>
                Jukebox
              </div>
              <div style={{ display: "flex", gap: "8px", flexWrap: "wrap" }}>
                {tracks.map((t) => (
                  <button
                    key={t.id}
                    onClick={() => play(t)}
                    style={{
                      padding: "8px 16px",
                      background: t.color,
                      border: "none",
                      borderRadius: "6px",
                      color: "#fff",
                      fontSize: "13px",
                      cursor: "pointer",
                    }}
                  >
                    {nowPlaying === t.id ? "♪ " + t.label : t.label}
                  </button>
                ))}
                <button
                  onClick={stop}
                  style={{
                    padding: "8px 16px",
                    background: "#475569",
                    border: "none",
                    borderRadius: "6px",
                    color: "#e2e8f0",
                    fontSize: "13px",
                    cursor: "pointer",
                  }}
                >
                  Stop
                </button>
              </div>
            </div>
          )}
        </div>
      );
    }} />
  );
}

コードの中身:

  • <Chat renderBubble={...} /> を使うと、プラットフォームのメッセージ一覧、入力欄、スクロールはそのままで、吹き出しの中身だけを自分で描けます
  • play() はジュークボックスのほかの曲を 1.5 秒かけてフェードアウトさせ、選んだ曲をフェードインさせます
  • 引数なしの api.stopAudio() は、鳴っているものをすべて止めます
  • nowPlaying はインターフェースの中だけの値なので、ページを再読み込みするとリセットされます。セーブに残したいときは api.setVariable("Now playing", t.id) で変数に保存し、api.variables["Now playing"] から読み戻します
  • ジュークボックスは最後のメッセージの下にだけ表示されます

自分で作ったプレイリストを順に進めたいときは、曲の終わりを待ち受けます。

tsx
React.useEffect(() => api.onAudioEnded((endedId) => {
  if (endedId === nowPlaying) playNext();
}), [nowPlaying]);

(これはループしないトラックでだけ呼ばれます。)


クイックリファレンス ​

トラックタイプ ​

タイプ用途よく使う設定
BGM背景音楽ループ オン、音量 0.5〜0.7
SFX一回だけ鳴る効果音ループ オフ、音量 0.7〜1.0
環境音音楽の下で鳴る環境のループループ オン、音量 0.2〜0.4

やりたいことと方法 ​

やりたいこと方法場所
プレイヤーが入ったら音楽を流すデフォルトプレイリスト + 自動再生オーディオ → BGM設定
変数で曲を切り替える条件付きBGM、変数条件オーディオ → 条件付きBGM
AI がある言葉を書いたら効果音条件付きBGM、AIキーワードオーディオ → 条件付きBGM
プレイヤーがある言葉を書いたら効果音条件付きBGM、プレイヤーキーワードオーディオ → 条件付きBGM
決まったターンで曲を切り替える条件付きBGM、ターン数(指定ターン または Nターンごと)オーディオ → 条件付きBGM
毎回のゲームの最初に決まった曲を流す条件付きBGM、セッション開始オーディオ → 条件付きBGM
物語に決めさせるトラックの いつ流すか / 何が起きたら一度鳴らすかトラックの設定
AI にトラックを触らせないAI による操作を許可 をオフトラックの設定
ビヘイビアの一部として音を鳴らす音楽を再生、効果音を再生、オーディオを停止ビヘイビアの効果
曲を流すボタン手順の 音声を再生 / 音声を停止プレイヤー画面
コードからすべて制御するapi.playAudio() / api.stopAudio()パネル → フロントエンドコード

条件付きBGM の項目 ​

項目役割
トリガー変数条件、AIキーワード、プレイヤーキーワード、ターン数、セッション開始
再生流すトラック
優先度複数のルールが当てはまったときは大きいほうが勝ちます
フェードイン(秒) / フェードアウト(秒)このルールで切り替えるときのフェード
前のBGMを停止音楽を音楽で置き換えるときはオン。SFX と環境音ではオフ
終了時条件を満たさなくなったときに流すもの:デフォルトプレイリストに戻る、前のトラックに戻る、または特定のトラック

インターフェースのコードのオーディオ API ​

メソッド説明
api.playAudio(trackId, opts)トラックを再生。opts:volume、fadeDuration(秒)、chainTo、maxDuration、duckBgm、loop
api.stopAudio(trackId?, fadeDuration?)トラックを止める。ID を省くとすべて止める
api.pauseAudio(trackId) / api.resumeAudio(trackId)その位置で一時停止・再開
api.onAudioEnded(cb)ループしないトラックが終わったら cb(trackId) を実行。購読解除の関数を返す
api.setAudioVolume("bgm" | "sfx", v) / api.getAudioVolume(...)プレイヤー側の音楽・効果音の音量

よくある問題 ​

症状よくある原因直し方
まったく音が出ないプレイヤーがページを操作するまで、ブラウザが音声をブロックしている最初のメッセージを待つ をオンにするか、最初のクリックで音楽が始まるようにします
音楽が 2 曲同時に鳴るルールやビヘイビアが、古い曲を止めずに BGM を始めた音楽のルールでは 前のBGMを停止 をオンに。ビヘイビアでは古い曲に オーディオを停止 を追加。コードでは playAudio の前にほかの曲を止めます
効果音で音楽が途切れるSFX のルールで 前のBGMを停止 がオンになっているSFX と環境音のルールではオフにします
AI がまったく曲を選ばないトラックに一行が書かれていない、または スマートトラッキング がオフいつ流すか を書き、カードの設定 の スマートトラッキング を確認します
AI が流してほしくない曲を流すAI による操作を許可 がオンそのトラックではオフにします
環境音がうるさい音量が大きすぎる環境音は 0.2〜0.4、音楽は 0.5〜0.7 に
変数のルールが発動しない条件が違う種類の値を比べている数値には数値の比較が必要です。文字は完全に一致させます
ルール同士がぶつかる優先度が同じルールごとに違う 優先度 を付けます。大きいほうが勝ちます

これはレシピ #14:オーディオデザインガイドです

まずはプレイリストから。音楽をゲームの状態に合わせたいときは条件付きBGMルールを、物語に選ばせたいときはトラックの一行を足し、コードはジュークボックスのようなものを作るときだけ使います。オーディオシステムが何を流すかをどう決めているのかは、上級編:オーディオ設計で詳しく説明しています。