オーディオデザインガイド
カードに音を付けるためのパターン集です。勝手に流れ出す 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 トラックを追加する
| 項目 | 爆発 | ドア |
|---|---|---|
| タイトル | Explosion | Door Open |
| トラックタイプ | SFX | SFX |
| ループ再生 | オフ | オフ |
| デフォルト音量 | 0.9 | 0.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 /> を置き換えます。
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"]から読み戻します- ジュークボックスは最後のメッセージの下にだけ表示されます
自分で作ったプレイリストを順に進めたいときは、曲の終わりを待ち受けます。
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ルールを、物語に選ばせたいときはトラックの一行を足し、コードはジュークボックスのようなものを作るときだけ使います。オーディオシステムが何を流すかをどう決めているのかは、上級編:オーディオ設計で詳しく説明しています。
