Edited at

[Unity] 0から始めるMusicEngine


♬ Music.cs

https://github.com/geekdrums/MusicEngine

MusicEngineは @geekdrums さんが製作されたライブラリです。

(こういう発表インタラクティブミュージックに関する記事を投稿 されている方です)

MusicEngineは最終更新が2015年ですが、Unity2018でも動作します。


🤔MusicEngineで何ができるか?

以下のPDFに解説が記載されています。

https://github.com/geekdrums/MusicEngine/blob/master/AboutMusicEngine.pdf

また以下のようなサンプルゲームも公開されています。

https://unityroom.com/games/musicpong

https://unityroom.com/games/spacetogo

MusicEngine は主に以下の機能を提供しています。


  • 今再生している音楽の情報を取得することができる

  • 今再生している音楽のリズムのタイミングが現フレームで合致したかを取得できる


🗂 Unityの中に取り込む

https://github.com/geekdrums/MusicEngine

zip.png

ZIPファイルをDLして解凍し、そのままUnityに入れ込んでください。

(中にある Music.cs だけでも稼働します)


⚙ MusicEngine の下準備


Music.csのアタッチ

任意のGameObjectにMusic.csをアタッチします。

(RequireComponet に指定があるため AudioSource も一緒にアタッチされます)

music1.png

次に一緒に追加された AudioSource に再生したいBGMを指定します。

music2.png


BGMの情報を指定する

Music.cs 自体には音楽のテンポを解析する機能はないため、こちらで一部の情報を指定する必要があります。

項目
内容

UnitPerBeat
何unitで1拍か

UnitPerBar
何unitで1小節が

Tempo
BPM/曲の速さ

4/4拍子の場合、UnitPerBeatは4 / UnitPerBarは4*4=16を指定します。

TempoはBPM (Beats Per Minute)を指定します。

1分間に何拍存在するか、という速さの指標で、多ければ早くなります。

これを的確に指定しないとリズムがずれます。

曲を自作する場合はBPMは自分で指定するので問題ないですが

BPMが記載されていないフリーの素材を使用する場合

このようなサイト を使用して、測定することになります (BPMは下1桁が 0 or 5 で構成されることが多いので測定で出た値を四捨五入しつつ、前後にずらして調整していくのが良いでしょう)

music3.png

これで下準備は完了です。

( Sections.Size を指定することで曲を複数に分割し、取り扱うことができますが、今回は割愛しています🙏)


🐄 リズムに合わせてオブジェクトを動かす

リズムに合わせてオブジェクトを拡大/縮小させてみます。

Music.IsJustChangedBeat を使用し、拍が切り替わるタイミングを取得します。

Music の一部のメソッドやメンバーは static 宣言されているため

どこのクラスからも参照することができます。

以下を動かしたいオブジェクトにアタッチします。

transform.scale を変更しているので3DモデルでもSpriteRendererでもuGUIでも何でもとりあえず動きます。

DOTweenをインポートしている前提です。


ChangeScale.cs

using UnityEngine;

using DG.Tweening;

public class ChangeScale : MonoBehaviour
{
public float Rate = 1.1f;
public float Time = 0.2f;

private Vector3 baseScale;

void Start()
{
this.baseScale = this.gameObject.transform.localScale;
}

void Update()
{
if (Music.IsPlaying && Music.IsJustChangedBeat())
{
this.gameObject.transform.DOScale(this.baseScale * this.Rate, 0.0f);
this.gameObject.transform.DOScale(this.baseScale, this.Time);
}
}
}


これでUI要素や背景オブジェクトを動かすだけでも楽しい!

適当に Rate や Time をいじって遊んでください。 Music と一緒にアタッチされたBGM用の AudioSource のピッチ変更にも追従するので、ピッチを動かして遊んでみるものいいでしょう。

music4.gif


🎨 小節ごとに背景色を変える

Music.IsJustChangedBar を使用し、小節が切り替わるタイミングを取得します。

1小節ごとに背景色を変えてみましょう。


ChangeColor.cs

using UnityEngine;

using DG.Tweening;
using UnityEngine.UI;

// SpriteRendererでも可
[RequireComponent(typeof(Image))]
public class ChangeColor : MonoBehaviour
{
public float Time = 0.2f;

void Update()
{
if (Music.IsPlaying && Music.IsJustChangedBar())
{
Color color = new Color(
Random.Range(0.5f, 0.8f),
Random.Range(0.5f, 0.8f),
Random.Range(0.5f, 0.8f),
1f
);
this.GetComponent<Image>().DOColor(color, Time);
}
}
}


music5.gif


💬 リズムに合わせて音を鳴らす

普段、SEを鳴らす際にはBGMとの関係性を意識せずに鳴らしていますが

クオンタイズを使用することで、BGMとSEがズレのない状態で (後方にやや貯めてから) 再生することができます。

Music.QuantizePlay に鳴らしたい効果音をアタッチした AudioSource を渡します。 Music 側でタイミングを調整した上で再生してくれます。

以下はボタンを押した時に音を鳴らすという例です。


SEPlayQuantizeButton.cs

using UnityEngine;

using UnityEngine.Events;
using UnityEngine.EventSystems;

[RequireComponent(typeof(AudioSource))]
public class SEPlayQuantizeButton : MonoBehaviour, IPointerDownHandler
{
public void OnPointerDown(PointerEventData eventData)
{
Music.QuantizePlay(this.GetComponent<AudioSource>());
}
}



最後に

応用的な機能の使い方は省きました「リズムに合わせてオブジェクトを動かす」「リズムに合わせて音を鳴らす」ということについて説明しました。ぜひぜひ試してみてくださいー!