【CRI ADX】無料版でもできる！UnityRoom向けにCRI ADXを実装する方法

こんにちは！ADXアンバサダーのこはと(kowato)です。

Unity向けCRIADXのWebGLビルド向け機能が、今回のアップデートより、**無料版（ADX LE）でも使用できる**ようになりました！

これまでは有料版のみに使用できる機能でしたが、これにより、CRI ADXを使用する全ユーザーが**UnityRoom**や**itch.io**など、UnityからWebプラットフォームへ向けたビルドにADXの機能を使うことが可能になりました。

↓例えばこんなようなことができます。

https://unityroom.com/games/criadx_webassembly_sample


本記事では「CRI ADXのUnityへの導入・実装」「UnityRoom向け対応」までの方法をご紹介します。

なお、チャプター１～４は初心者向けの解説となります。
「**UnityRoom向け対応の部分だけ知りたい！**」という方は、**チャプター５「音を鳴らす（準備編）」** から御覧ください。

# CRI ADXとは？
CRIミドルウェア社が開発したサウンドミドルウェアであり、UnityやUnrealEngineのようなゲームエンジンに組み込むことで、インタラクティブミュージックなどのより多彩なサウンド表現が可能になります。
詳しい導入方法はこちらをご参照ください。（個人規模なら無料で使用できます！）

https://qiita.com/Takaaki_Ichijo/items/16e6501fc07f5b3b3377


# 前提（バージョン情報など）
本記事の実装において使用した各ソフトのバージョンは以下のとおりです。
・AtomCraft:3.52.03
・UnitySDK:3.11.00
・Unity:6000.0.24f1

# 実装すること
今回はシンプルに「GUIボタンを押したら任意の音声を再生する」機能を実装し、なるべく最速でサウンドを実装する方法をご紹介します。

ADXの環境をインストールされていない方は、始める前にあらかじめAtomCraftのインストール、Unity向けPluginのダウンロードをお願いします。

https://game.criware.jp/products/adx-le/#:~:text=%E3%81%8C%E5%8F%AF%E8%83%BD%E3%81%A7%E3%81%99%E3%80%82-,%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89,-%E3%80%8CCRI%20ADX


※今回の実装は、Awbデータを使用しない前提の内容となります。

# １:UnityProjectを作成
任意の名前のProjectを作成します。2D、3Dどちらでも構いません。
今回は3Dで作成しました。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/36548bd9-ef1b-7232-d1b7-73ad657abb2b.png)

# 2:プロジェクトにADXプラグインをインポート
プロジェクトを開いたら、早速ADX環境をインポートしていきます。
といっても、上記でダウンロードしたUnityPluginをインポートするだけです。
Assets > Import Package > Custom Packageから、ダウンロードしたプラグインファイルの
「cri\unity\plugin\criware_unity_plugin_v2_43_50_le_ja.unitypackage」を選択し、パッケージをプロジェクトにインポートします。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/532ff365-06de-9ff5-6025-feef0e2a761f.png)


これでADXの機能が使えるようになりました。


# 3:SoundDataのフォルダを作成
次に、ADX向けに作成したデータを保存するためのフォルダを作成します。
Assets直下に「SoundData」のフォルダを作成しましょう。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/f23fa6c7-2910-6358-1b9b-b30ab9d28579.png)


:::note info
Acb,Acf等のADXのデータは「StreamingAssets」フォルダで管理することもできますが、今回は **「StreamingAssets以外」のフォルダで管理** します。理由は後述にて。
:::


# 4:AtomCraftで音声データを作成、Unityへエクスポート
外部オーサリングソフトであるAtomCraftで、音声データ(Acb,Acf)を作成します。
基本的には
AtomCraftに音声データ(.wav,.ADX,.HCA,.HCA-MX)を登録
→Cueと呼ばれる再生単位を作成し、Cueに音声を適用、
→（Cueに各種設定を適用）
→書き出し　
という手順になってます。


今回はフリー音源のBGMを一つ登録してみます。
まずはお好きな音源をダウンロードし、拡張子が.wab以外の場合は、AudacityなどのアプリケーションでWAVE形式に変換しておきましょう。

https://www.audacityteam.org/blog/audacity-3-5/

データが用意できたら、AtomCraftを開き、Projectを作成

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/cdd246ef-7e2d-9734-5a02-c8a022e1a728.png)


ワークユニット名はデフォルトのままで大丈夫です

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/8228fcac-355d-e677-6bed-e999a3108b11.png)


「マテリアルツリー」タブへ行き、マテリアルルートフォルダーに任意のBGMの.wavファイルをドラッグアンドドロップ

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/cb1363c2-7d0f-f790-3de4-b7e41fd14875.png)



追加したら「ワークユニットツリー」タブに行き、「CueSheet_0」の上で右クリックを押し「新規オブジェクト＞キュー「ポリフォニック」の作成」を選択

![7-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/ed2eadf2-312c-58fd-be6c-d5871be622e0.png)


「マテリアルツリー」タブから、登録したBGMの.wavファイルを作成したCueのタイムラインにドラッグアンドドロップ。
波形データが追加されるので、開始位置をタイムラインの一番左に合わせておきましょう。
なお「F5」を押すことでCueの再生プレビューができます。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/70146826-ccf9-bf89-3ec0-4de1142bd4b4.png)

:::note info
「Cue」とは、CRI ADXの基本的な再生単位であり、ゲーム内でこのCueを指定、再生することでCueに適用された波形データが再生されます。
:::



追加できたら「マテリアルツリー」タブから「CueSheet_0」の上で右クリックし「Atomキューシートバイナリのビルド」を選択

![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/62dcc9c3-9b40-7c78-ee64-751501547ad1.png)

保存先は、作成したUnityProjectの「SoundData」フォルダを選択してください。
「階層出力」のチェックボックスをOFFにしたら、「ビルド」を押して.acb、.acfファイルを書き出します。


![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/8044160d-1bf3-bb33-0ef7-c234e69ecb5c.png)


:::note warn
波形データの「ストリーミングタイプ」設定を「ストリーム」や「ゼロレイテンシーストリーム」に設定すると、上記のAcb,Acfファイルに加えてAwbファイルが出力されますが、今回は便宜上この機能は使わないため、使用する波形データのストリーミングタイプは全て「デフォルト（メモリ）」で行うようにお願いします。
:::


# 5:音を鳴らす（準備編）
さて、ここまではCRI ADXの基本的な使用方法です。
ここからは、**WebGLビルドにむけて必要な対応を含みます**。

## 前提
UnityでADXを使用するうえで、従来はStreamingAssetsにAcbなどのデータを入れ、ビルド時に内容を読み込むことで音声を再生していましたが、UnityRoomへアップロードするビルドには **StreamingAssetsフォルダを含むことができません**。

この対策としては様々な方法があるかと思いますが、より簡単な方法として**AssetSupppotPackage**を用いた方法を紹介します。

AssetSupportPackageでは、Unityプロジェクトに追加したAcbやAcfを **Unityアセットとして参照することが可能** になり、今回はこれを用いて、作成したAcb,AcfをOnMemoryデータとしてビルドに組み込みます。

https://game.criware.jp/manual/unity_plugin/latest/contents/addon4u_assetsupport.html

## AssetSupportPackageのインポート

UnityPluginのAssetSupportPackageをインポートします。

UnityのAssets > Import Package > Custom Packageから、
「cri\addons\asset_support\plugin\cri_asset_support_addon_v1_2_06+0_9_06_ja.unitypackage」
をプロジェクトにインポートします。

Unityでこのように表示されるようになればOKです。
（**必ず「StreamingAssets」以外のフォルダへデータを置いてください**)

![9_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/a7f75326-4f6e-68fa-7a6b-3bef6cf2cdf0.png)

:::note info
CriAssetSupportでは、**StreamingAssetsフォルダに格納されているAcb,Acf,Awbは例外としてCriAssetとして認識されません** 。そのため「SoundData」などの別の名前のフォルダに格納することで、上述のOnMemoryなどの設定が可能になります。
:::

## SceneにAssetSupport用オブジェクトを追加する
次はAtomCraftで作成した音声データをゲーム内で読み込めるように設定します。
まず、Hierarchy上で「CriWareErrorHandler」「CriWareLibraryInitializer」を作成します。

![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/7eb7c47d-01b6-5c8d-f657-92657b3fb055.png)


作成したら「CreateEmpty」で空のゲームオブジェクトを作ります。名前は何でも大丈夫です。
今回は「CRIWARE」としました。

![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/15ed9160-0689-9446-b5e5-f3973032238d.png)

作成したオブジェクトに「AddComponent」で「CRI Atom Assets」を追加します。

![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/2516e08a-d3dc-e12b-6805-f5a763625317.png)

これは実行時に.acb、.acfデータを読み込み、ゲーム全体で音声を読み込めるようにするコンポーネントです。
大雑把に言えば、CRIADXでは「AudioSource」のようなGameObjectを作らずとも、このようなコンポーネントで音声を一括ロードした後、適宜スクリプトから音声を読み込み・再生をすることができ、今回はその機能を使います。

コンポーネントを追加したら、先ほど作成した.acf,.acbをここに登録します。

![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/1d1bc728-f941-0e91-f072-849baeffaf35.png)


これで再生の準備ができました。

# 6:音を鳴らす（実装編）
では、実際に音声を再生する実装をしましょう。
今回は2つのスクリプトを作成します。
新しくスクリプトを作成し、名前を「SoundManager」とします。
コードの内容は以下です。

```C#:SoundManager.cs
using UnityEngine;
using CriWare;//←忘れずに追加
using CriWare.Assets;//←忘れずに追加


public class SoundManager : MonoBehaviour
{
    CriAtomExPlayer BGMPlayer;

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        //プレーヤー作成
        BGMPlayer = new CriAtomExPlayer();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    /// <summary>
    /// 任意のCueNameの内容を再生
    /// 再生内容は適宜再生元で設定したCriAtomCueReferanceを引数として参照し、再生します。
    /// </summary>
    public void PlaySound(CriAtomCueReference cueRef)
    {
            //もし再生中であれば停止
            if (BGMPlayer.GetStatus() == CriAtomExPlayer.Status.Playing)
            {
                BGMPlayer.Stop();
            }

            BGMPlayer.SetCue(cueRef.AcbAsset.Handle, cueRef.CueId);
            BGMPlayer.Start();
     
    }

}

```
今回作成したスクリプトでは、**PlaySound()** で引数として渡されたCriAtomCueReferanceの内容を再生する機能を実装しました。

## コード解説

CRIADXの音声再生では、基本的に「Acbのロード＆ExPlayerの作成→SetCue()→Start()」の流れで音声を再生することができます。
Acbのロードにはいくつかの方法がありますが、本記事では先ほど「CRIWARE」GameObjectに追加した「CRIAtomAssets」コンポーネントでのロードが完了しているため、スクリプトからの明示的なロードは不要です。

https://game.criware.jp/manual/unity_plugin/latest/contents/classCriWare_1_1Assets_1_1CriAtomAssetsLoader.html

CriAtomExPlayerのリファレンスはこちら

https://game.criware.jp/manual/unity_plugin/latest/contents/classCriWare_1_1CriAtomExPlayer.html

また、再生には **CriAtomCueReferance構造体** を渡すことで再生を行っています。これはCriAtomAssetsプラグインに含まれる機能です。
これには以下のような利点があります。

+ 再生Cueの指定を**Inspectorからドロップダウンで**行うことが可能
+ 本来別々のAcb情報とCue情報を、**まとめて一つの値として渡すことができる**
+ 「存在しないCueを指定する」等の**エラーの回避**


https://game.criware.jp/manual/unity_plugin/latest/contents/structCriWare_1_1Assets_1_1CriAtomCueReference.html

ということで、実際にPlaySoundを呼び出すスクリプトを作成します。
スクリプトを新規作成し、名前を「SoundPlayer」にします。
コードの内容は以下です。

```SoundPlayer.cs
using UnityEngine;
using CriWare.Assets;

public class SoundPlayer : MonoBehaviour
{
    //再生したい音声のAcb、CueNameを設定する
    public CriAtomCueReference cueReferance;
    //キャッシュ用
    SoundManager soundManager;
   public void OnButtonPlaySound() 
   {
       //SoundManager取得
        if(soundManager == null)
        {
            soundManager = FindFirstObjectByType<SoundManager>();
        }
        //SoundManagerの再生メソッドにCue情報を引数として渡す
        soundManager.PlaySound(cueReferance);
   }
}


```
この **cueReferance** にInspectorから再生したいCueを設定することができ、そのままSoundManagerのPlaySound()の参照値にすることで、指定した音声を再生できる仕様となっています。

## スクリプトのアタッチ

スクリプトを作成したら、Hierarchyに新しくゲームオブジェクトを作成し、SoundManager.csをアタッチします。

![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/c479c883-34ac-11c0-ca6f-7641623824ff.png)

SoundManagerの作成ができたら、最後に再生する仕組みをつくります。

:::note info
記事ではButtonを押して音声を再生する仕組みを実装しますが、ここはご自身のゲームの内容に沿って変更してください。
:::

HierarchyからUI>Buttonを作成し、Buttonに作成した「SoundPlayer」スクリプトをアタッチします。

![15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/463ce60c-42df-c565-dc79-58432f44fb94.png)

![30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/84de7257-062f-d037-3707-c88abdc2aa63.png)


スクリプトがアタッチできたら、SoundPlayerに再生したいサウンドを設定し、OnClickにSoundPlayerのPlaySound(string)メソッドを登録しましょう。

「SoundPlayer」の設定

![31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/a19ff94c-844b-3f14-e2eb-88ffc3e7c4e9.png)

![32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/7dbfd265-24f2-cff2-0859-207d74363c0c.png)

「Button」の設定

![33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/de3efa0d-dc63-6c6e-434c-f73713c2cf5e.png)

![34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/12f16880-2faa-4130-a44d-f063a6741d04.png)

これで音声を再生できます。
Playボタンを押してゲームを再生し、Buttonを押して音声の再生を確認しましょう。

# 7:WebGL向けにビルドする
現在はEditorでのみ再生できてますが、これらをUnityRoomでも再生できるようにするには,
いくつかの変更が必要になります。

## AcbAsset,AcfAssetのDeployTypeをOnMemoryにする
SoundDataフォルダ内のAcbAsset,AcfAssetをInspectorで確認し「DeployType」が「OnMemory」以外になっている場合は「OnMemory」に設定し、Applyで設定を更新しましょう。

![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/de59e79b-a276-dd4d-29ce-97f036702565.png)



## PlatformをWebGLに切り替える
最後にPlatformをWebGLに切り替えます。
ビルドの際はPlayerSettingでCompressionFormatを「Gzip」に変更し、DevelopmentBuildはOffにしましょう。

![20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/30234db0-1602-a480-83bc-8877241f8e1a.png)

![22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/0a3f190f-33da-5649-0070-f3e3f6bcf365.png)

![21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/5fecd508-1808-64a5-b212-18b6d2ea4f32.png)


設定が終わったら、Buildボタンを押して任意のフォルダにビルドし、作成されたフォルダをUnityRoomに登録します。UnityRoomへの詳細な登録方法はこちらもご参照ください。

https://qiita.com/kurisaka_konabe/items/73471f00439befea807d

# 終了！
UnityRoomへアップロードしたゲームをUnityRoomで再生し、実際に音声が再生されればOKです！
今回はButtonを押し、BGMを再生する簡単な仕組みを実装をしましたが、SoundManagerの同じメソッドを使うことで、他のスクリプトから曲名を指定するだけで簡単に音声を再生できます。
CRIWAREでは、他にもUnityでCRIADXを使用するための **公式チュートリアル** も公開されていますので、そちらもぜひご覧ください。

https://game.criware.jp/learn/tutorial/unity/

また、Cueの設定によっては、同じ再生でもランダムな効果を与えたり、音楽のBPMに合わせた演出も簡単に実装することができるようになります。

https://game.criware.jp/learn/tutorial/atomcraft/atomcraft_shokyu_08/

https://qiita.com/nimushiki/items/2542de52c88e5b27e681


これからはUnityRoomでもADXを用いた様々なサウンド演出が可能になります。
Unity1Weekや自作ゲームの音楽、効果音にちょっとしたエッセンスを加えたい方は、ぜひCRIADXの色んな機能に触れてみてください！



# おまけ-Awbの実装について 
Awbは、長尺のBGMなど容量の大きいデータを読み込む際、再生遅延を回避するために設計された、CRI ADX独自の圧縮形式のファイルです。CueSheetの内容に「ストリーム」等のストリーミング設定がされている波形データを含む場合、このファイルが作成されます。

https://game.criware.jp/manual/adx2_tool/latest/criatom_tools_atomcraft_awb_file.html


このファイルは仕様上、 **CriAssetsSupportのOnMemory機能が使用できません**。 
そのため、WebGLでのロード時、AcbファイルがAwbファイルを要求する場合はAddressable等を使用してデータをオンライン取得する必要があります。

## 音声データをAssetBundle化してWebサーバーから取得する

ここでは、任意のサーバーにビルドしたAssetBundleを配置し、LoadAssetAsync等のメソッドでデータをオンライン取得する想定で、AssetGroupの作成～ロードまでを解説します。

### 1:「CRIWARE」オブジェクトをPrefab化

記事内で作成したCRIWAREオブジェクトをPrefab化します。
今回はこのPrefabをAddressable経由でロードし、音声処理を行うようにします。


### 2:AcbAssetsにAwbを追加する

次に、参照したいAwbAssetsをAcbAssets(「CRIWARE」Prefab内で参照しているもの)に設定します。
この際、**AcbAssets、AwbAssets共に**「DeployType」を「**Addressable**」に変更してください。
なお「Addressable」の設定は、プロジェクトにAddressableパッケージをインポートすることで選択できるようになります。

https://game.criware.jp/manual/unity_plugin/latest/contents/addon4u_assetsupport_assets_import.html#addon4u_assetsupport_assets_import_deploy_type


![a_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/0a96b7a9-85bc-4c70-c9b4-c5fbe4ded328.png)

![a_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/9cf47291-643a-b541-b4d3-a8721c574e93.png)


### 3:AssetGroupにアセットを追加してロード
最後に、上で作成した「CRIWARE」Prefabと、AcbAssetsの「Addressable」チェックボックスをONにしてAssetGroupへ追加し、SoundManagerのコードを以下のように修正します。（今回はPrefabのアドレスネームを「CRIWARE」としてあります）

![a_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450329/af5e4e10-f5c4-163a-80be-2e51dc98f325.png)



```SoundManager.cs

using UnityEngine;
using CriWare;
using CriWare.Assets;
using UnityEngine.AddressableAssets;
using System.Threading.Tasks;

public class SoundManager : MonoBehaviour
{

    CriAtomExPlayer BGMPlayer;


//ここから追加--------------------------------------------------------------------
  async void Awake()
  {
      AsyncOperationHandle<GameObject> prefab = Addressables.LoadAssetAsync<GameObject>("CRIWARE");
     
      await prefab.Task;
      // ロードが完了したらPrefabを生成
      if (prefab.Status == AsyncOperationStatus.Succeeded)
      {
          GameObject prefabInstance = Instantiate(prefab.Result);
      }
  }

//ここまで------------------------------------------------------------------------

    // Start is called once before the first execution of Update after the MonoBehaviour is created
 void Start()
 {

     //プレーヤー作成
     BGMPlayer = new CriAtomExPlayer();

 }

 // Update is called once per frame
 void Update()
 {
     
 }

 /// <summary>
 /// 任意のCueNameの内容を再生
 /// 再生内容は適宜再生元で設定したCriAtomCueReferanceを引数として参照し、再生します。
 /// </summary>
 public void PlaySound(CriAtomCueReference cueRef)
 {
         //もし再生中であれば停止
         if (BGMPlayer.GetStatus() == CriAtomExPlayer.Status.Playing)
         {
             BGMPlayer.Stop();
         }

         BGMPlayer.SetCue(cueRef.AcbAsset.Handle, cueRef.CueId);
         BGMPlayer.Start();
 }
}

```

以上で設定は終わりです！
なお、unityRoomでAddressableを使用する場合は
・CRIAsset用BuildScriptの作成、参照
・データのwebサーバーへのアップロード
・loader.jsの「streamingAssetsUrl」の変更
などの対応が必要です。詳しくは以下の内容もご参照ください。


https://game.criware.jp/manual/unity_plugin/latest/contents/addon4u_assetsupport_addressables_usage_usecribuildscript.html

https://zenn.dev/uimss/scraps/b544d1952f6934