【Unity】Timeline × CRI ADX2で実現するムービー中のサウンド演出

# 最初に

本記事の内容は、TimelineとCRI ADX2を組み合わせて使用する場合に、どういったことができるか、サンプルを通じて学び、実装をしていくものとなります。

UnityのTimelineは、時間軸に沿った演出を簡単に作成・制御できるツールです。これにCRI ADX2を組み合わせることで、より高度なサウンド演出を実現することができます。特に、サウンドと映像の同期や、キャラクターの動きに合わせた音響効果を実装する際には非常に強い組みあわせとなるでしょう。

<br>
本記事の対象読者は以下の通りです。

- UnityのTimelineを使ってムービーシーンを演出したい方。
- CRI ADX2を使用して、サウンドと映像をシームレスに連携させたい方。
- ゲーム内のカットシーンやムービーのサウンド演出にこだわりたい方。

### 環境

本記事の環境は以下の通りとなります。

- Unity：2022.3.52f1（CRI社が提供しているサンプルを開くため）
- OS：Windows
- CRI ADX SDK：ADX LE Unity SDK（3.11.00）
- CRIツール：Windows用（3.54.02）

<br>

# CRI ADX2入門に最適な記事3選

まず本記事の内容に本格的に踏み込んでいく前に、CRI ADX2を触ったことがない方向けに、入門記事を紹介致します。
<br>

- [「**ADX2 動画チュートリアル**」](https://criware.info/adx2_tutorial_videos/?utm_source=chatgpt.com)
    - 動画となりますが、体系的に学ぶのに役立つと思います。
- [**CRI ADX2 LEを使ってみる(音が鳴らない時の対処を追加)**](https://am1tanaka.hatenablog.com/entry/2020/01/16/182021)
- [**UnityAudioからCRI ADX2に乗り換えて簡単にリッチな音響体験を作ろう！　Part1**](https://qiita.com/Hirai0827/items/8396c67983ba75b5dbe1)

<br>
もしも一度も触ったことがなければ、上記の記事に目を通してみてください。

<br>

# Timeline入門に最適な記事3選

続いて、Unityの機能であるTimelineを入門するのに良さげな記事を紹介致します。
<br>

- [**はじめてのUnityのTimeline**](https://note.com/hayu500ml/n/n975b589fc6bc?utm_source=chatgpt.com)
- [**【Unity】手軽に演出を構築！はじめての Timeline 入門**](https://www.midnightunity.net/unity-timeline-introduction/?utm_source=chatgpt.com)
- [**【Unity】Timelineの作成方法徹底解説**](https://yurinchi2525.com/20240226timeline/#google_vignette)

<br>
Timeline自体かなり便利な機能ですので、一度は実際に触ってみることを強くオススメします。

<br>

# CRI ADX2のサンプルチェック

:::note warn

もしまだサンプルが手元にない方は、以下の公式サイトにアクセスして、ページ下部にある「ダウンロード」からご自身の環境に合わせたSDKとツールをダウンロードしてください。本記事ではUnityを使用して確認するため、「ADX LE Unity SDK」と、ツールの「Windows用」を使用します。

[無償版サウンドミドルウェアCRI ADX LE - CRIWARE for Games](https://game.criware.jp/products/adx-le/)

予め、以下の公式マニュアルに沿ってツールユーザーライセンス認証を行ってください。

[CRI ADX: ツールユーザーライセンス認証について](https://game.criware.jp/manual/native/adx2/latest/criatom_tools_license_about.html)

:::



それでは実際にCRI ADX2のサンプルを開いて、どのように実装されているのか確認していきましょう。Timelineを用いてサウンドの再生実装がされているサンプルは以下のSceneとなります。

- `Assets/CriAssetSamples/Scenes/Scene_04_Timeline.unity`

このサンプルに関する公式ドキュメントは以下の通りとなります。

[CRIWARE Unity Plugin Manual: [Asset Support] Timeline 再生](https://game.criware.jp/manual/unity_plugin/latest/contents/cri4u_samples_addon_asset_scene04.html)

<br>

開くと以下のように３つのボタンが並んでいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/4fafa19f-1fc3-2bda-6a1a-33062ce437aa.png)


「Play」ボタンをクリックすると、BGMが流れて合間にSEなどが再生されることがわかります。

<br>

Hierarchyを見てみると、「Timeline」という名前のGame Objectが存在しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/2ce659f1-3eed-c71d-f135-a73e8430fb05.png)


選択してInspectorを覗いて、Dicrectorパラメータに設定されているTimelineという名前のアセットをダブルクリックしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/10153b67-3012-8862-757a-f632368c9d22.png)


<br>

Timelineタブで以下のように、CRIのアセットを再生する用のトラックとクリップ群が登録されているのが確認できると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/57465918-be9a-901e-17d4-04ac3925ed1f.png)

<br>

ここでは **「Cri Atom Track」** という、CRIの独自形式のサウンドファイルの再生タイミングを視覚的に設定できるトラックが使用されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/8977fd63-40ae-d397-4f6b-be6fa916a320.png)


### トラックのパラメータ

- **Aisac Control**：
トラック曲線で制御するAISACコントロールの名前を指定します。
- **Stop On Wrapping**：
ループ再生されるトラックで、新しいループが開始する際に前回のループ再生を停止するかどうかを設定します。
- **Stop At Graph End**：
Timelineの再生が停止したときに、このトラックのサウンド再生も停止するかどうかを設定します。
- **Apply Playable Speed**：
Playableに指定した再生速度を音声にも適用するかどうかを設定します。
- **Check Position Within Clip**：
クリップ内での再生位置を変更した際に、音声の再生位置も同期して変化させるかどうかを設定します。
- **Show Mono Waveform**：
トラック上で各クリップの最初のチャンネルの波形を描画するかどうかを設定します。`false`の場合、全チャンネルの波形が描画されます。

:::note

**AISACって？**

AISAC（Automatic Interactive Sound Control）は、CRI ADX2における音声のリアルタイム制御機能で、音量やピッチなどのパラメータを動的に変化させることができます。

詳しい内容は[公式ドキュメント](https://game.criware.jp/manual/adx2_tool/latest/criatom_tools_atomcraft_aisac.html)を確認することをオススメします。

:::

<br>

続いて、Timeline上で設定されている **「Cri Atom Asset Clip」** というClipを見てみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/df0bebc1-054f-5599-a2c6-8872dc537bf5.png)


### クリップのパラメータ

- **キューシートとキューの指定**：
再生するキューシートとキューを指定します。
- **Stop Without Release**：
クリップ終了時の停止時に、リリースを有効にするかどうかを設定します。
- **Muted**：
クリップをミュート（無音）にするかどうかを設定します。
- **Ignore Blend**：
クリップのブレンド設定を無視するかどうかを設定します。
- **Loop Within Clip**：
クリップ内で指定したサウンドをループ再生するかどうかを設定します。
- **Stop At Clip End**：
クリップの末尾で再生を停止するかどうかを設定します。
- **音量・ピッチ・AISACコントロールの値**：
これらの値は、Timelineのカーブビューで時間経過に伴う変化を制御できます。

<br>

クリップ同士が重なるように動かすと、簡単に**フェードイン/フェードアウト**が実装できます。

![1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/a15e532c-568e-8849-f2e0-9e95fd2c3c94.gif)


このフェードの変化値自体はカーブエディタで曲線設定ができるので、自然なクロスフェード効果をお手軽に実現できます。

<br>

**音量・ピッチ・AISACコントロール**をクリップ内の時間経過に合わせて、値を自由に変化させたい場合は、タイムライン上でカーブエディタを使用し編集することも可能です。

![2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/f0245655-169c-65c1-63ba-1b41a1efba59.gif)


<br>

:::note

Timelineで使えるCRIツールは２種類あります。

**CRI Atom Unity Timeline**

- 音声や効果音の再生および制御に特化しています。
- サウンド演出のタイミングやボリューム、ピッチの調整をTimeline上で管理することが可能です。
- キャラクターのセリフや環境音、効果音をムービーに同期させる演出に向いてます。

**CRI Mana Unity Timeline（CRI Sofdec用）**

- 映像再生と音響の同期に特化しています。
- ムービークリップの再生タイミングをTimeline上で細かく制御し、映像と音声をシームレスに組み合わせることができます。
- オープニングムービーやカットシーンにおける映像とサウンドの同期演出に使用できます。

:::

<br>

上記で説明した内容は公式マニュアルを見て頂くことでも確認が可能です。

[CRIWARE Unity Plugin Manual: CRI Atom Unity Timeline拡張](https://game.criware.jp/manual/unity_plugin/latest/contents/atom4u_extension_timeline.html)

<br>

# プロジェクト独自のサウンドクリップを作る

ここまでは、サンプルと公式から提供されているトラックやクリップを使用しているものを見てきました。

しかし実際に使用する場合には、プロジェクト専用のサウンドクリップが欲しくなると思います。

ですので、CRIツールから提供されている便利機能を活かしつつ、プロジェクト独自のクリップを用意する方法を紹介します。環境としては先ほどのサンプルプロジェクトをそのまま流用しておりますので、サンプルプロジェクトをDL済みの方であればいくつかスクリプトを足せば、すぐに確認ができます。

まずは、`CustomTimelineBehaviour.cs`を作成します。

```csharp
using System;
using CriWare.CriTimeline.Atom;

namespace {あなたのプロジェクトの名前空間}
{
    // CriAtomBehaviourは、CRI ADX2のサウンド再生や制御を管理する基底クラス
    // CriAtomBehaviourを継承してカスタム挙動を作成
    [Serializable]
    public class CustomTimelineBehaviour  : CriAtomBehaviour
    {
        // 例として用意したキャラクターのIDです
        private string characterId;

        public void SetCharacterId(string characterId)
        {
            this.characterId = characterId;
            
            // キャラクターIDやその他情報から、動的にキューIDを変えたりなど
        }
        
        // Timelineが再生される際に毎フレーム呼ばれるメソッドです
        // playable: 現在再生中のPlayableオブジェクト
        // info: 再生フレームの詳細情報
        // playerData: 連携するオブジェクトやデータ（通常はAudioSourceなど）
        public override void ProcessFrame(Playable playable, FrameData info, object playerData)
        {
            // CRI Atom側での標準的なサウンド再生処理を行います
            base.ProcessFrame(playable, info, playerData);
            
            // 毎フレーム、サウンドと連携したカスタム処理を追加可能
            // 例: キャラクターのアニメーションに連動したLipsync再生など
        }
    }
}
```

<br>

続いて、`CustomProjectClip.cs`を用意します。

```csharp
using System;
using CriWare.Assets;
using UnityEngine;
using UnityEngine.Playables;

namespace {あなたのプロジェクトの名前空間}
{
    [Serializable]
    public class CustomProjectClip : CriAtomAssetClip
    {
        // CustomTimelineBehaviourに渡すためのCharacterIDをここで設定できるように
        [SerializeField]
        private string characterId;

        // CustomTimelineBehaviourのテンプレートを保持します。
        // これにより、再生時に各クリップごとの挙動を定義するためのテンプレートとして機能します。
        // デフォルト値として新しいインスタンスを作成し、初期化します。
        [SerializeField]
        private CustomTimelineBehaviour customTemplateBehaviour = new();

        // Playable（再生可能なオブジェクト）を作成するメソッドです。
        // Timeline上でクリップを再生する際の振る舞いや挙動を定義します。
        public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
        {
            // ScriptPlayable<T>はカスタムビヘイビアのインスタンスをタイムライン内で扱える「再生可能オブジェクト（Playable）」として動作させるための型です。
            // CustomTimelineBehaviourのインスタンスをScriptPlayableとして作成します。
            // これにより、カスタムビヘイビアのテンプレートをPlayableGraphに登録します。
            // PlayableGraphはタイムライン内のクリップやアニメーションなどの要素や再生順序、依存関係を管理する役割を持っています。
            var playable = ScriptPlayable<CustomTimelineBehaviour>.Create(graph, customTemplateBehaviour);
            
            // 作成したPlayableからCustomTimelineBehaviour（ビヘイビア）を取得します。
            // ビヘイビアはタイムライン上で再生される具体的なアクションや処理を定義します。
            var behaviour = playable.GetBehaviour();

            behaviour.SetCharacterType(characterId);

            // 作成したPlayableを返します。このPlayableはTimeline上でクリップとして扱われます。
            // Timelineが再生されると、ここで定義したビヘイビアが動作します。
            return playable;
        }
    }
}
```

<br>

上記２つのクラスを用意することで、以下のように「Cri Atom Track」上でカスタムしたクリップを作成することができるようになります。

![3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/915f5557-da74-7521-c44d-ab3e521bc3e9.gif)



<br>

Cueパラメータは忘れずに設定してください。

また、もともと存在しているVolume・Pitch・AISAC Valueは機能しなくなり、代わりにCustom Template Behaviour内のVolume・Pitch・AISAC Valueが使えるようになります（カーブエディタも問題なく使用できます）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/241d9190-377d-6d4f-d920-492047cc2cde.png)


<br>

## シンプルなカスタムクリップを作る場合は

もしも、以下のような場合は、単に「PlayableAsset」を継承して用意するシンプルなCRIサウンド再生用クリップを作ることもできます。

- そこまでリッチじゃなくていいし、使いきれない機能は必要ないけど、プロジェクト用のサウンド再生クリップが欲しい
- 既にサウンドマネージャーがあって、そちらで細かい制御・管理をしたい

<br>

この場合、`CustomProjectClip.cs`を以下のように変更します。

```csharp
using System;
using CriWare.Assets;
using UnityEngine;
using UnityEngine.Playables;

namespace {あなたのプロジェクトの名前空間}
{
    [Serializable]
    public class CustomProjectClip : PlayableAsset
    {
        // CriAtomCueReferenceは、CRI ADX2のキューを参照するための構造体です。
        // [SerializeField] 属性により、インスペクター上でキューを選択可能になります。
        // これにより、エディター上でドロップダウンリストからキューを選択できるようになります。
        public CriAtomCueReference cue;
        
        [SerializeField]
        private string characterId;

        public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
        {
            var playable = ScriptPlayable<CustomTimelineBehaviour>.Create(graph);
            var behaviour = playable.GetBehaviour();

            behaviour.SetCharacterId(characterId);
            behaviour.SetCueId(cue.CueId);

            return playable;
        }
    }
}
```

ただしこの場合は、次に説明するプロジェクト独自のサウンドトラックを用意する必要があります。

<br>

# プロジェクト独自のサウンドトラックを作る

クリップだけではなくトラックもプロジェクト独自のものを用意してあげると、更にカスタマイズ性が広がります。CRI ADX2の機能をフル活用する場合は、**CriAtomTrack**を継承して作ることをオススメします。

`CustomSoundTimelineTrack.cs`を作成します。

```csharp
using CriWare;
using CriWare.CriTimeline.Atom;
using UnityEngine.Timeline;

namespace {あなたのプロジェクトの名前空間}
{
    // TrackColor属性は、Timelineエディター上でトラックの表示色を設定します。
    // ここではRGB値で緑色(0.0f, 1f, 0f)に設定しています。
    [TrackColor(0.0f, 1f, 0f)]
    
    // TrackClipType属性は、このトラック上に配置できるクリップの型を指定します。
    // ここではプロジェクト管理がしやすいようにCustomProjectClip型のクリップのみ追加可能と定義しています。
    [TrackClipType(typeof(CustomProjectClip))]
    
    // TrackBindingType属性は、このトラックがバインド（関連付け）できるオブジェクトの型を指定します。
    // ここではサウンド再生用にCriAtomSourceBase型のオブジェクトにバインドできるよう定義しています。
    [TrackBindingType(typeof(CriAtomSourceBase))]
    
    // CriAtomTrackを継承することで、CRI Atomの機能を活用したサウンド制御が可能になります。
    public sealed class CustomSoundTimelineTrack : CriAtomTrack { }
}
```

上記のクラスを用意することで、独自のトラックが作成できるようになりました。

![4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/a8b4b335-da06-5bca-43ef-11d1365de875.gif)


<br>

## シンプルなカスタムトラックを作る場合は

「PlayableAsset」を継承して用意したクリップを使う場合は、以下のようにトラックも単純化できます。

```csharp
using UnityEngine.Timeline;

namespace {あなたのプロジェクトの名前空間}
{
    [TrackColor(0.0f, 1f, 0f)]
    [TrackClipType(typeof(CustomProjectClip))]
    public sealed class CustomSoundTimelineTrack : TrackAsset { }
}

```

<br>

# まとめ

本記事では、**UnityのTimelineとCRI ADX2を組み合わせたサウンド演出の実装方法**について解説しました。

**今回学んだポイント**

- TimelineとCRI ADX2の連携で、Timelineムービーと音声を簡単に同期
- CRI ADX2のサンプルプロジェクトを活用して、基本的な機能と実装例を確認
- カープエディタを使って、音量やピッチの変化を簡単に制御
- カスタムクリップとトラックの作成により、プロジェクトに応じた柔軟なサウンド制御を実現

ここから更に応用して、高度なサウンド演出にチャレンジしてみてください！
Timelineを拡張する記事は多く存在しているので、それらを参考にしつつあなたのプロジェクト独自のTimelineを作ってみましょう（出来上がったら是非記事にしてください）。