はじめに
Unityには標準で物理演算エンジンが備わっているので、簡単に物理挙動を実装することが出来ます。しかし、その衝突に適切な音を発生させるのは、音量の調整や音のバリエーションの用意が必要になり、大変です。ましてや大量のオブジェクトがぶつかる場合はなおさらです。
本記事ではUnityとサウンドミドルウェア「ADX for Unity」を用い、ランダム性があり物理的な状態を考慮した効果音の実装例を紹介します。
この記事は「ADX2+UE4で、物理挙動にランダム性のある効果音をつける」のUnity版です。元記事作者のSigさんの許可を得て作成しています。
https://qiita.com/SigRem/items/77644c292a1f3e1e16fd
前提
動作確認環境
Windows 10 Home 20H2
Unity 2020.3.27f1 + ADX LE Unity SDK 3.06.03
CRI ADX LE Tools for Windows 3.46.09
前提記事
CRI ADXの導入方法や基本的な操作については、以下の記事を参照して下さい。
Unityのサウンド機能をADXで強化する
https://qiita.com/Takaaki_Ichijo/items/16e6501fc07f5b3b3377
やること
- AtomCraftでキューを作成
- パラメータを調整し、音に性質を追加する
- Unityにインポート
- テストシーンを作成、サウンド処理を実装する
実装
AtomCraft側
まずは、再生する音データの作成を行います。ADXにおいては、再生用のデータはUnityとは別のツール「AtomCraft」を使います。その手順については、元の記事(UE4向け記事)の同名の項と同じになりますので省略しています。
本記事の手順を試す場合は、まず元の記事の該当項目を進めてから本記事を進めてください。UE4版との違いとして1点、「Atomキューシートバイナリのビルド」画面で、一番左下のオプション「UnityAssets出力」にチェックを入れるのを忘れないようにして下さい。
Unity側の実装
キューシートのインポート
AtomCraftからエクスポートしたファイルをインポートします。
スクリプトの作成
以下のようなRandomHit.csを作成します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RandomHit : MonoBehaviour
{
public CriAtomSource criAtomSource;
private void OnCollisionEnter(Collision collision)
{
criAtomSource.Play();
}
}
動作は単純で、オブジェクトが何かにぶつかったら音を再生します。
テストシーンの作成
以下のようなシーンを作成します。
- CriWareLibraryInitializer、CriWareErrorHandler
- 基本コンポーネント、GameObject>CRIWAREから作成
- CRIWARE
- 自動生成
- Cue_Impact_Metal(CriAtomSource)
- 前項でインポートした音源
- Plane
- デフォルトでOK、色を変えると見分けやすい
- Cube
- Rigidbodyをアタッチ
- 先程作成したRandomHit.csをアタッチ
- CriAtomSourceにCue_Impact_Metal(CriAtomSource)を設定
テストシーンの実行
ここまで出来たら忘れずに保存し、実行しましょう。
Cubeを上から落としたり、Ctrl+Dで増やしたりして衝突させて音を鳴らします。AtomCraftで設定した通り、ランダム性のある衝突音が確認できます。
応用
場合によってはこのままでも問題ないですが、ほんの少しだけ当たった場合や勢いよく当たった場合でも同じように音が鳴ってしまいます。そんな状況をカバーするために改良を加えます。
スクリプトの改良
RandomHit.csを以下のように修正します。
private void OnCollisionEnter(Collision collision)
{
if (collision.impulse.magnitude < 1) return;
criAtomSource.volume = Mathf.Clamp( collision.impulse.magnitude / 15, 0, 3);
criAtomSource.Play();
}
collision.impulse.magnitudeは衝突による運動量の大きさを取得することができます。
よって、if文では小さな衝突の場合音がならないようにし、次の文では勢いに応じてボリュームを変化させる、という処理をしています。
破壊音などのバリエーションを加えたい
さらに大きな衝突が起きた場合に破壊音を鳴らしたい、というケースがあるかもしれません。しかし、今回利用した「ランダムノーリピート」のキュータイプには、特定の音を選択して鳴らすという方法がありません。
そのため、別のキュータイプを利用する、もしくは別のキューシートとして破壊音を用意しコードの方で衝突音・破壊音を鳴らし分ける、といった工夫が必要になります。