はじめに
前回以下のような 距離から音量を取得する機能を実装しました。こちらをせっかくなら いい感じの見た目にしようと思い、Audio Visualiser
の作成を行いました
成果物
動作環境
- Unity 2021.3.4f1
実装
各音源から距離と音量を取得・表示する
以前に実装について書いたので以下をご覧ください。
Visualiser UIの作成
今回のAudio Visualiserは 16等分割した円の画像を使って向きと大きさを表現しています。
まずはこちらのUIを作る作業からやっていきます
(完成UIの拡大版)
(完成したUIのパーツUI : 白で塗りつぶししているため、Web上だと見えないため画像をダウンロードして使用してください)
画像作成アプリは、なんでもいいですが 今回は firealpaca を使っていきます。
放射線上の下書きと円形の下書きを書いて、1/16の円を作っていきます。
次に Unity上で、以下の感じで Image の Fill Amountを変更してUIに変化を持たせたいため、画像を横向きに変更します (画像作成時に横向きにしておくとこの作業がスキップできます)
画像の回転は Windows標準機能のフォトアプリの編集機能が優秀だったため、こちらを使っていきます。 回転する角度は 11.25度(360 / 32) ですが、小数点以下は指定できないみたいなので11度回転させてあげます
できた画像を Unity上にimportして、Texture Typeを Spriteにしておきます。 そのあとに 円の中心に回転したいため Sprite Editorを使って Pivotを円の中心に変更します
シーン上に配置すると、以下のようにImageが円の中心を軸にきれいに回転するようになっています。
Audioデータから Visualiser UIをリアルタイで更新する
今回は Visualiserは以下のように要件定義して実装をしていきます
- 聞こえている音とVisualiser上の色を同じ色にする(見やすくするため)
- 聞こえている方向を 360度の円形上で表現する
- 聞こえている音量を 一つの軸の高さで表現する
上を満たすための AudioData
は以下のようにしました。
public class VisualizerAudioData { public float AudioValue; public Vector2 AudioVector; public Color32 AudioColor; }
1 はほぼ何もしていないので、詳細は省略します。
2.3については以下のようにしています。
簡単に説明すると Visualiserの画像数(表現できる音の種類 = 16個) の配列に その方向の音量で一番大きいデータを入れる
処理をしています。
まずは Player と Audioの位置から 角度を以下のように計算します
public static float Vector2ToAngle(Vector2 vector2) { var angle = Mathf.Atan2(vector2.y, vector2.x) * Mathf.Rad2Deg; if (0f <= angle) return angle; return 360f + angle; }
次に上で計算した角度がどの向きグループに属するのかを計算します
例えば 角度が 0度の場合は 配列[0]に属する、角度が 120度の場合は 120 / (360/16) = 5.33 ≒ 6なので 配列[6] に属する。
private int VisualizerDataIndex(float angle) { return Mathf.CeilToInt(angle / (360f / _visualiserData.Length)) - 1; }
すでに入っているAudioDataの音量よりも大きいかどうかを比較して、大きい場合のみ更新します。
public void UpdateVisualizerData(VisualizerAudioData data) { if (data.AudioValue <= _minValue) return; var angle = Vector2ToAngle(data.AudioVector); var oldValue = _visualiserData[VisualizerDataIndex(angle)].AudioValue; if (oldValue < data.AudioValue) { _visualiserData[VisualizerDataIndex(angle)] = data; } }
これで データクラスの更新が終わったので、配列データを View側に 渡して Visualiser UIを更新していきます。
MVP の設計にしているため、 PresenterがModelのデータ配列をもらって View側(MonoBehaviour) を更新します
サンプルプロジェクトのクラス図
まとめ
ModelとViewを分割しているため、3D Visualiserとかにも応用できそう??
HoloLensやOculusQuestとかで周りの環境音を取得して、表示したら面白そうですね!(どこかでやりたい)