Udonsharpを使って音源の波形を取得して、ゲーム内の物体に反映させてみよう
正直初回のやつは簡単すぎたと思います。そして味気なさすぎたと思います。
なので今回は簡易的でもいいので実際にオーディオビジュアライザーを作ってみましょう!
ここから完全にC#が絡んできます。
ただ、すべてのスクリプトはほぼコピペで完結させます。
なのでC#ができない方も諦めずにがんばってください。
Q.そもそもUdonって?
A.VRCでもなんか複雑なことができるようになるやつ
以上。それくらいの認識でいいです。
筆者はUdonsharpしか触ってないのでUdonとかよくわかりません。
1.VisualStudioの導入
ここからDLして導入してください。
メモ帳などでもコーディングはできなくはないですが、VisualStudioのほうが効率はいいです。
Visual studio Communityは個人で使用する場合は無料なので、こちらを使用しましょう。
※30日使用後にサインインが必要になるので、アカウント登録したくない人はメモ帳アプリで頑張りましょう。
※※そもそも全部コピペでいいよって人はここから先のコーディングも全てメモ帳で完結します。
Visual studioをインストールする際は赤枠の場所にチェックを入れてインストールしてください。
2.Udonsharpのダウンロード
以下のページよりダウンロードを行ってください。
クリック後に画像のようなページへと遷移するので、赤枠のunitypackageをダウンロードしてください。
3.音源のダウンロード
今回は 魔王魂 様のシャイニングスターを使用させてもらいます。
形式は今回はMP3を使用します。
これでファイルの準備は完了です。
4.プロジェクトへの音源をインポートと音源の設置
プロジェクトは前回作成したものを使いましょう。
前回の記事を見てない方はとりあえずPlane1枚とVRCWorldがHierarchyに入っているプロジェクトを作ったらOKです。
プロジェクトを開いたら、このあたりにドラッグ&ドロップします。
ファイルが増えてきたらフォルダで整理したほうがいいですが、それはもっと凝ったワールドを作るときでいいです。
次は音源を再生できるようにします。
Hierarchy(左のウィンドウのPlaneのすぐ下辺り)を右クリックして、Audio→Audio Sourceを選択してください。
AudioSourceがHierarchy上に作成できたら、画像のような画面になると思います。
なっていない人はHierarchy上のAudio Sourceをクリックして選択状態にして、右側ウィンドウの左上の赤枠部分「Inspector」をクリックしてこの画面を表示してください。
ここまでできたら、先程インポートした音源(シャイニングスター)をAudio sourceオブジェクトのAudio sourceコンポーネント(Inspectorのウィンドウに表示されている場所)のAudioClip欄にドラッグ&ドロップしてください。
用語が増えてきたのでちょっとややこしくなりますが、赤枠で囲んだ部分を赤枠で囲んだ場所に入れればいいです。
この状態になったらOKです。
画面中央上部の再生ボタンみたいなやつをクリックして再生したときに、曲が再生されたらここまでの作業は完了です!
5.オブジェクトを配置する
オブジェクトは「もの」って言い換えてもらって大丈夫です。
※今回はハードコーディング(作るのは楽だけど修正がめんどくさい方法)で一旦実装します。
汎用性を持たせるのは次回以降にしておきます(説明とかが長くなるので)。
Hierarchy上で右クリック→3D Object→Cubeを選択してください。
Cubeが作成できたら、図のようにInspector上のtransformの数値を設定してください。
・オブジェクトの名前を「Cube1」 に
・Positionの数値をx→5,y→0,z→-5.5に
・Scaleの数値をx→0.5,y=1,z=0.5に
これを複製して8個分作ります。
Hierarchy上のCube1にカーソルを合わせて、キーボードのCtrlを押しながらDボタンを押すと、選択したオブジェクトが複製されます。
(1)と名前の付いたオブジェクトができていれば成功です。
複製したオブジェクトを横に等間隔に並べていきたいので、
複製したオブジェクトの名前を「Cube2」
Inspector上のtransformのxの値を4にしてください。
これを繰り返して、Cube1-Cube8を作成してください。
それぞれのCubeのInspector上のtransformのxの値が5,4,3,2,1,0,-1,-2になっていればOKです。
このとき、下の画像のように等間隔に並んだ白い柱ができているはずです。
音源の音の波形でこの柱の形が変化するようにします。
6.Udonsharpを使ってオブジェクトの操作を行う
まだUdonsharpをimportしてなかったのでimportしましょう。
importの方法忘れた人は前回の記事を参考にしてください。
Udonsharpのimportが終わったら、赤枠あたりの位置で右クリック→Create→U# Scriptを選択してください。
なんかウィンドウが出るので名前を「AudioVisualizer」と入力して「保存」を押してください。
ここで決めた名前は途中で変えないほうがいいです。
保存を押して少しすると赤枠の位置に白い英文が表示されます。赤文字でなにか表示されているうちは操作しないでください。
白い英文が表示されたら、赤枠のファイル「AudioVisualizer.cs」をメモ帳なりVisualStudioなりで開いてください。
開いたらこんな画面になると思います。初期設定は見づらいので左下の倍率を200%位にしておきましょう。
この記事を参考にしてコーディングをしていきましょう。
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
public class AudioVisualizer : UdonSharpBehaviour
{
public GameObject cube1;
public GameObject cube2;
public GameObject cube3;
public GameObject cube4;
public GameObject cube5;
public GameObject cube6;
public GameObject cube7;
public GameObject cube8;
public GameObject audioObj;
private AudioSource audios;
private float[] waveData_;
private float[] size;
private int num;
void Start()
{
audios = audioObj.GetComponent<AudioSource>();
waveData_ = new float[128];
size = new float[8];
num = waveData_.Length / size.Length;
}
void Update()
{
audios.GetOutputData(waveData_,1);
for(int h = 0; h < size.Length; h++)
{
size[h] = 0f;
}
for (int i = 0; i < waveData_.Length; i++)
{
int index = (int)(i / num);
size[index] += waveData_[i];
}
cube1.transform.localScale = new Vector3(0.5f, size[0],0.5f);
cube2.transform.localScale = new Vector3(0.5f, size[1],0.5f);
cube3.transform.localScale = new Vector3(0.5f, size[2],0.5f);
cube4.transform.localScale = new Vector3(0.5f, size[3],0.5f);
cube5.transform.localScale = new Vector3(0.5f, size[4],0.5f);
cube6.transform.localScale = new Vector3(0.5f, size[5],0.5f);
cube7.transform.localScale = new Vector3(0.5f, size[6],0.5f);
cube8.transform.localScale = new Vector3(0.5f, size[7],0.5f);
}
}
とても汚いコードですが、今回は動かすことを優先にします。
説明も後回しにします。
これをそのままコピペして先程のAudioVisualizer.csファイルに貼り付けてください。
貼り付けたら保存してください。
ここまで終わったら、Unityの方に戻ります。
コードが間違っているとここに赤色でエラーメッセージが出ます。
今回はコピペなので出ないはずです。このように白色のメッセージが出ていれば現状は問題ありません。
先程作成したAudioSourceを選択して、右側のInspector欄の一番下の「Add Component」を選択してください。
出てきた検索欄にudonって打ち込むとなんか出るので、Udon Behaviourを選択しましょう。
AudioSourceのInspector欄になんか増えるので、先程作成したスクリプト(末尾がCSじゃない方)をProgram Sourceの欄にドラッグ&ドロップしてください。
使うのはU#マークのついてる、末尾がAssetの方です。#マークの方ではありません。
そもそも#マークの方は入れようとしても入らないんですけどね。
そうするとこんな感じになって、なんか欄が増えます。
左側のHierarchyウィンドウにあるやつと名前を対応させてあるので、Hierarchyウィンドウにあるやつをドラッグ&ドロップして1個ずつ入れていきましょう。
HierarchyウィンドウにあるCube1を、右側のAudioSourceのInspectorのUdonBehabiour欄の「Cube1」の欄にドラッグ&ドロップすればいいです。Cube2-8も同様に同じ名前のところに入れていきましょう。AudioObjの欄にはAudio Sourceをドラッグ&ドロップすればOKです。
ここまで終わったら、ウィンドウ中央上部の再生ボタンを押してみましょう。
曲に合わせて白い柱のサイズが変わっていればOKです!
おつかれさまでした!これで連動は完了です!
ps.コード部分についての説明
public GameObject cube1;
public GameObject cube2;
public GameObject cube3;
public GameObject cube4;
public GameObject cube5;
public GameObject cube6;
public GameObject cube7;
public GameObject cube8;
public GameObject audioObj;
private AudioSource audios;
private float[] waveData_;
private float[] size;
private int num;
コーディングするとき、なにを使うかまず「宣言」する必要があります。
「これからこれらを使います」という意味です。
アクセス範囲、型、名前 の順で記載します。
誰が使えて、何を入れられる、◯◯という名前の付いた箱というイメージです。
[]が型の後ろについているものは配列です。2個以上のオブジェクトを入れることができます。
Unityで使う場合、publicだとUnityの上で書き換えたりすることができます。
privateだとUnity上では基本的に確認できません。
必要に応じて使い分けましょう。詳しくは次回以降で。
void Start()
{
audios = audioObj.GetComponent<AudioSource>();
waveData_ = new float[128];
size = new float[8];
num = waveData_.Length / size.Length;
}
宣言をした際に箱を作ったので、箱の中身を入れましょう。
もしくは、配列の場合は箱のサイズを決めましょう。
public型は中身を入れなくてもUnity上で入れる場合もあるのでエラーになりませんが、
private型は中身を入れないとエラーになります。
void Update()
{
audios.GetOutputData(waveData_,1);
for(int h = 0; h < size.Length; h++)
{
size[h] = 0f;
}
for (int i = 0; i < waveData_.Length; i++)
{
int index = (int)(i / num);
size[index] += waveData_[i];
}
cube1.transform.localScale = new Vector3(0.5f, size[0],0.5f);
cube2.transform.localScale = new Vector3(0.5f, size[1],0.5f);
cube3.transform.localScale = new Vector3(0.5f, size[2],0.5f);
cube4.transform.localScale = new Vector3(0.5f, size[3],0.5f);
cube5.transform.localScale = new Vector3(0.5f, size[4],0.5f);
cube6.transform.localScale = new Vector3(0.5f, size[5],0.5f);
cube7.transform.localScale = new Vector3(0.5f, size[6],0.5f);
cube8.transform.localScale = new Vector3(0.5f, size[7],0.5f);
}
ここで行っているのは
1.audiosという名前のオブジェクトから、waveData_という名前の配列に波形データを入れる
2.sizeという配列の中身をすべて0にする
3.sizeという配列の1番目にはwaveData_の1番目から16番目までのデータの合計を、
2番目には17番目から32番目のデータの合計を・・・という風に16個ずつデータを足したものをsizeという配列の中身に入れる
4.size配列の1-8の値を、cube1-8の高さに設定する
ということを処理しています。
今回はかなり雑に、動けばいいという前提でコードを書いてます。
次回はどのような動作をさせたいか文章にまとめてから、コーディングをしてみましょう。