ゲームの銃撃音実装バリエーションその２ 武器の状態に合わせて音を自動的に変える

ゲーム開発におけるサウンド演出実装の難しい点は、「ゲームは常に状況が同的に変化する」ということです。動画制作と異なり、ゲームではプレイヤーの入力によって音が鳴る状況はダイナミックに変化します。
3Dのゲームでは単にサウンド素材をステレオで鳴らすだけではなく、ゲーム内の状況に沿った音の聞こえ方・方角・音の種類を場面に合わせていく必要があります。
今回は三人称シューティングゲームにおけるサウンド実装を想定し、プレイヤーが銃のモードを自由に変えながら、ゲーム中のカメラの視点も変わるような場合の音の実装について解説します。

## 前提となる知識

この記事は
「ゲームの銃撃音バリエーションを増やしつつコード量を減らす」https://qiita.com/Takaaki_Ichijo/items/fced234c2aca996f9fd5

と、「ゲームの状況に合わせてサウンドエフェクトのかかり具合を変える」
https://qiita.com/Takaaki_Ichijo/items/957dd09112b9939ff083
の姉妹編です。

また、本記事は統合型サウンドミドルウェア「CRI ADX2」及び付属のサウンドオーサリングツールAtom Craftの触り方をある程度理解している方向けの解説です。
初めてADX2を使う、という方は各エンジンへの導入の記事を先に参照ください。

Unity: Unityのサウンド機能をADX2で強化する
https://qiita.com/Takaaki_Ichijo/items/16e6501fc07f5b3b3377

UE4：　ADX2 for UE4の導入で、一歩上のサウンド表現を（導入編）
https://qiita.com/SigRem/items/4250925f6d66a4fd287a


## 「属性付与」演出で銃の発射音に別の音を追加する
戦闘の要素があるゲームでは、ゲームシステムに深みを持たせるために「属性」の設定をつけることが多くあります。
例えば炎は氷に強いが土に弱い、雷は水に弱い...など、武器や防具に属性をつけ、そのバランスでゲーム内の戦略に強弱をつけるものです。

シューティングンゲームのサウンド実装において、「銃の発射音」にこうした属性の概念で音が変わるような実装を要求されることを考えてみてください。
素直に考えるならば、「雷モードのときの音」「氷モードのときの音」のように、サウンド素材をバラバラに用意して、そのつど鳴らすファイルを変える実装が思いつきます。
ただ、銃の種類が数十個、属性の概念も数十個、となると用意すべき音が膨大なバリエーションを持つときはどうすればいいでしょう。

２つ目の手段としては、「銃の発射音」と「属性を表す音」を別々に用意しておき、同時に鳴らすことです。これなら大量のバリエーションをデータとして持たずに済みそうです。
しかしながら、再生するべきファイルが２つになり、同時に再生する音の数をカウントして制御していた場合は、その判定が複雑になります。
加えて、属性の種類に応じてボリュームを調整したい...などとなった場合はどうでしょうか。

そこで今回は、CRI ADX2を使って「属性がつく銃の音」の設計と管理について紹介します。

### 元素材の用意
銃の発射音は、前々回の記事と同じフリー効果音サイトの「[効果音ラボ](https://soundeffect-lab.info/)」から取得します。

「属性」にあたるサウンド素材は、Tsugi株式会社の「[DSP Anime](http://tsugi-studio.com/web/jp/products-dspanime.html)」を使って生成します。

![dspアニメ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19010/625c2ae4-8f6f-0d33-09a0-6ff0add3457f.png)


<iframe width="560" height="315" src="https://www.youtube.com/embed/Up6helTmzV8" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

これらのサウンド素材を用いて、サンプルとして今回は「通常の銃の発射音」と「雷属性のついた銃の発射音」を切り替えできる音声データを作成します。

### 「セレクタラベル」を使ったキューの設定

銃の音に「属性」の概念を導入するには、ADX2の「セレクタラベル」機能を使います。

まずは、ベースとなる「銃の音」を用意します。この設定は前々回の記事[ゲームの銃撃音バリエーションを増やしつつコード量を減らす](https://qiita.com/Takaaki_Ichijo/items/fced234c2aca996f9fd5)と同様です。

![handganbase.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19010/55dee3a7-6efd-b383-d5ca-f85403ed5d88.png)

このキューを直接再生せずに、「属性」を設定したキューの中にトラックとして埋め込んで再生する仕組みを取ります。
「キューリンク」という機能を用いて、キューの中にキューを設定します。

![キューリンク.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19010/71c26c0f-d51d-8924-5a55-da07913a6b22.png)

次に、この銃の音と同時に再生する「属性」を表す音のトラックを作ります。

![雷属性.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19010/2ebba8e4-6912-68fe-a131-d3e389d39f82.png)
キューリンクトラックの下にある「Track_Electricity」が雷の「バリバリ」という音の素材です。
このキューをプレビュー再生すると、当然両方が同時に再生されます。一定の設定を行ったときのみ、下のトラックが再生されるようにしましょう。

### プロジェクトツリーで「攻撃の属性」を表すセレクタラベルを作成する

プロジェクトツリーで、ゲームにおける「武器の状態」を示すラベルデータを作成します。
「セレクタフォルダ」の下に新しいセレクタとして「Enchant」を作ります。

![セレクタフォルダ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19010/1133281a-680a-6619-c10c-8855e86ef54a.png)

Enchantセレクタフォルダの中に、無属性攻撃を示す「None」と、雷属性攻撃を示す「Thunder」のセレクタラベルを作成します。

### セレクタラベルをキューのトラックに指定する

トラックにプロジェクトツリーで作成したセレクタラベルを指定します。

![セレクタラベルの指定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19010/34e53c94-85e0-a178-3175-48ea85538587.png)

銃の発射音は常になってほしいので何もラベルは付けず、２番目のトラックの雷の音に「Thunder」ラベルを指定します。
これでキューの設定は完了です。メニューの「表示 -> セッションウィンドウ」を選択し、ラベルの有無で音が変わるかどうかをチェックします。

![セッションウィンドウでセレクタの動作を確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19010/20d7c7e4-e600-1c46-1d4e-7eae40ecd1b3.png)

### セレクタラベルをキューの再生時に指定

プログラムからセレクタラベルを指定して再生する
ゲーム側で「ラベル」を指定して再生します。

#### Unityの場合
CriAtomSourceクラスメンバのCriAtomExPlayerクラスにああるSetSelectorLabelメソッドで切り替えます。
Enumを用意しておくと明瞭です。

https://game.criware.jp/manual/unity_plugin/jpn/contents/classCriAtomExPlayer.html#a70e17b68b0e8cb38589a966e71395d64

```PlayGunShot.cs
public class PlayGunShot: MonoBehaviour 
{
    public CriAtomSource atomSource;
    public CriAtomExAcb acb; //再生するキューが入ったキューシート
    public enum GunEnchant {Fire, Ice, Thunder};

    public PlayHandGunShot(GunEnchant  gunEnchant)
    {
         atomSource.player.SetCue(acb, "Handgun_Shot");

         if(gunEnchant == GunEnchant.Thunder)
         {
             atomSource.player.SetSelectorLabel ("Enchant","Thunder");
         }
         atomSource.Play();
    }
}
```

#### UE4の場合
ブループリントAPI「Atom Component」の「Set Selector Label」ノードを使います。

https://game.criware.jp/manual/ue4_plugin/contents/criware_ue4_api_AtomComponent_SetSelectorLabel.html

### ほかの武器効果音へセレクタラベルの転用
一度作成したセレクタラベルは再利用できますので、例えば剣を振る音や防具で攻撃を防御する音で「属性」を表したい場合も使えます。

## 銃を構えている位置で聞こえる方向性を変える

2000年代以降のTPS（三人称シューティング）では、自キャラが中央より左右にどちらか寄っていて、肩越しにレティクルが見えているゲームが多くなりました。バイオ４やギアーズオブウォー、Fallout 3以降のTPS視点などです。
こういった視点の場合、敵などの見たいものと自キャラがかぶってしまったときのために、左右の視点切り替えが実装されています。効果音の一部も、この左右の寄りにそって鳴る位置が変わるとより自然です。
そこで、プレイヤーの位置（ゲームのカメラ視点）によって、音の聞こえる方向が変わる実装を考えてみます。

### キューごとのラベル指定ではなく、全体設定を切り替える
さきほどの「属性」で説明したセレクタラベルは、各キューに毎回「今回鳴らすときはこのラベル」という指定を行っていました。
ですが、ゲーム中のカメラ位置が変わって音の聞こえる方向が変わる、というのはすべての武器から発せられる音が影響されるということです。
こういったサウンド全体に影響を及ぼすゲーム内の変化には、セレクタではなく「ゲーム変数」機能を用いると効果的です。

ゲーム変数は、ADX2側に0~1の変数を用意しておき、特定のキューは必ずその数値を参照して音の鳴り方を変更する機能です。
ゲーム内の状況が変わった時にその変数の値を変更すれば、関連するキューはその値をもとに鳴り方が変化します。

0から1の数値が変化するにしたがって、再生中の音を滑らかに変化させたい....という場合は「AISAC」機能を使うとよいのですが、今回の例のパターンは発射音が鳴った直後に視点を変更したとき、音もシームレスに変化してしまっては不自然です。

ゲーム変数を使って、「視点が右の場合」と「左の場合」の設定をあらかじめ作っておき、一気に切り替える方針で考えていきます。

### ゲーム変数とキューの用意

まずはプロジェクトツリーで「ゲーム変数」フォルダを開き、「PlayerSCereenPositon」変数を新規作成します。

![ゲーム変数の用意.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19010/eb656492-a37e-920c-8671-c4d70241869b.png)

また、先ほど作成したHandgun_Shotキューを再び入れ子にします。今回は同じキューを２トラックに並べます。

![パンの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19010/0085a1bd-2430-33b0-6aeb-5a8e4b4ae3ff.png)

そのうえで、それぞれのトラックの「パン[5.1]」設定を別の喪に変えます。一つ目は右に振り、二つ目は左に振ります。

### キューにゲーム変数を指定する

キューとゲーム変数を関連させるために、キューのインスペクタで「スイッチ」を選び、先ほど作成したゲーム変数「PlayerScreenPosition」をスイッチ変数欄に指定します。

![スイッチの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19010/106eb5de-107b-0ce6-c705-ba983d757993.png)

これでこのキューはゲーム変数に応じて再生されるトラックが変わるようになりました。
先ほどと同様「セッションウィンドウ」を開き、「ゲーム変数」ウィンドウを開いてスライダーを動かしながらプレビュー再生してみましょう。

![スイッチ変数の確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19010/0068f9c1-82d5-d9ee-c57d-6b777566ce09.png)

スライダーが0のときと1のときで再生される音の聞こえる方向が変わることが確認できます。

スクリプトからの「ゲーム変数」変更方法は[前回記事](https://qiita.com/Takaaki_Ichijo/items/4777ba953e7992a872e4)と同様です・

## 効果音のバリエーションを豊かに、ただし手間は増やさずに

冒頭で紹介したように、たくさんの音のバリエーションがあると再生時にどの音を再生するべきかの管理が大変になります。

ADX2とその機能セレクタラベル、ゲーム変数を活用することで、スクリプトからの呼び出しを複雑化せずに、ゲーム内の状況を反映する音を組むことができます。

今回は説明しませんでしたが、ピッチ変更やフィルタの適用なども組み合わせれば、より広い表現が可能です。ぜひチャレンジしてみてください。