- はじめに
- 1. 準備
- 2. メインとなるスクリプトとゲームオブジェクトの作成
- 3. 再生/停止ボタンの制御(②PauseButton)
- 4. 10秒戻り/進み機能(②BackButton、④ForwardButton)
- 5. 再生時刻の表示(⑤TimeText、⑥TimeSlider)
- 6. 再生速度の制御(⑦SpeedText、⑧SpeedSlider)
- 7. 音量の制御(⑩VolumeSlider)
- その他
はじめに
以前の記事で下の動画の音楽再生アプリのようなものを紹介しましたが、今回はその制作方法について紹介します。
Unityで作成した音楽再生アプリみたいなやつ#Unity pic.twitter.com/2o2IIMirNL
— ミドリ黄 (@MidorikiProg) 2022年4月9日
1. 準備
Projectウィンドウで右クリック、「Create」⇒「Scene」と選択して新しいシーンを作成する。
次に、Hierarchyの+ボタンを押して「UI」⇒「Canvas」の順に選択してキャンバスを作成したら下の画像のように
- Render Mode…Screen Space - Camera
- Render Camera…作成したシーン上にあるMainCamera
と設定を行う。
そしたら、再生ボタンなどに使用する画像を準備してアセットに追加する。
Canvasに適宜用意した画像を利用してUIを追加していき以下のように画面を作成する。
番号 | ゲームオブジェクト名 | UIの種類 | 機能など |
---|---|---|---|
① | NameText | Text | 再生している曲名の表示 |
② | BackButton | Button | 押すと10秒戻る 用意した画像「DoubleTriangle」を反転(Scale X=-1)にして使用 |
③ | PauseButton | Button | 再生/停止を制御 用意した画像「Triangle」を使用 |
④ | ForwardButton | Button | 押すと10秒進む 用意した画像「DoubleTriangle」を使用 |
⑤ | TimeText | Text | 再生時刻と音楽の長さを表示 |
⑥ | TimeSlider | Slider | 再生時刻をスライダーで表示 ここから再生時刻を制御はできない。 |
⑦ | SpeedText | Text | 再生速度が何倍かを表示 |
⑧ | SpeedSlider | Slider | 再生速度を変更できる |
⑨ | VolumeText | Text | 「音量」という文字の表示 スクリプトなどからの制御は行わない |
⑩ | VolumeSlider | Slider | 音量を調節できる |
2. メインとなるスクリプトとゲームオブジェクトの作成
Hierarchyから「Create」⇒「Empy」でゲームオブジェクトを作成して名前を「MusicController」に変更。以降作成するスクリプトはすべてこのオブジェクトに追加する。
さらにAudio Sourceを追加してAudioClipに再生したい音楽ファイルを追加する。
続けて制御用のスクリプト「MusicController.cs」を作成して次のプログラムを記述して、下の画像のように画面を設定する。
音楽ファイルは魔王魂のものを使用しています。
プログラム
- シングルトンにすることで以降に作成するスクリプトからaudioSourceに簡単にアクセスできるようにしている。
- ゲームが開始したらNameTextにaudioSourceに設定したclip名を表示する。
using UnityEngine; using UnityEngine.UI; public class MusicController : MonoBehaviour { [SerializeField] Text nameText; public AudioSource audioSource; public static MusicController I { get; private set; } private void Awake() { I = this; } private void Start() { nameText.text = audioSource.clip.name; } }
3. 再生/停止ボタンの制御(②PauseButton)
「PauseController.cs」を用意してプログラムを記述して「MusicController」オブジェクトにアタッチし設定をします。
プログラム
- 関数Start内のbutton.onClick.AddListenerでPauseButtonを押したときの処理( 再生/停止の変更)を割り当てている。
- 再生はaudioSource.Pause()で、停止はaudioSource.Play()で制御できる。
- Update関数内でaudioSource.isPlayingから音楽が再生中か判断して、画像を変更する。
using UnityEngine; using UnityEngine.UI; public class PauseController : MonoBehaviour { [SerializeField] Button button; [SerializeField] Image buttonImage; [SerializeField] Sprite triangleSprite; [SerializeField] Sprite boxSprite; private void Start() { //イベントを追加 button.onClick.AddListener(PauseUnPause); } private void Update() { //再生中なら「||」、停止中なら「▶」にアイコンを設定 if (MusicController.I.audioSource.isPlaying) buttonImage.sprite = boxSprite; else buttonImage.sprite = triangleSprite; } //再生・停止の変更 void PauseUnPause() { if (MusicController.I.audioSource.isPlaying)//停止 { MusicController.I.audioSource.Pause(); } else { //MusicController.I.audioSourceを何度も書くのは面倒なので簡潔に宣言 AudioSource aS = MusicController.I.audioSource; //詳しいことはわからないがこれがないとダメ aS.timeSamples = (int)(aS.clip.frequency * aS.time); aS.Play(); } } }
4. 10秒戻り/進み機能(②BackButton、④ForwardButton)
「StepController.cs」を用意してプログラムを記述して「MusicController」オブジェクトにアタッチし設定をします。
プログラム
- Awake関数内でそれぞれのボタンを押したときの処理( 再生/停止の変更)を割り当てている。
- audioSource.timeが現在の再生時刻なのでこれを±10することで再生時刻を変更している。
- ±10秒したときにaudioSource.timeが0より小さくなったり、音楽ファイルの長さよりも大きくなったりしないように制御をしている。
using UnityEngine; using UnityEngine.UI; using UnityEngine.Events; public class StepController : MonoBehaviour { [SerializeField] Button backButton; [SerializeField] Button forwardButton; private void Awake() { //「▶▶」ボタンの設定 UnityAction action1 = () => { float time = MusicController.I.audioSource.time + 10; if (time > MusicController.I.audioSource.clip.length) { MusicController.I.audioSource.Stop(); } else { MusicController.I.audioSource.time = time; } }; forwardButton.onClick.AddListener(action1); //「◂◂」ボタンの設定 UnityAction action2 = () => { float time = MusicController.I.audioSource.time - 10; if (time < 0) { MusicController.I.audioSource.time = 0; } else { MusicController.I.audioSource.time = time; } }; backButton.onClick.AddListener(action2); } }
5. 再生時刻の表示(⑤TimeText、⑥TimeSlider)
「TimeLineController.cs」を用意してプログラムを記述して「MusicController」オブジェクトにアタッチし設定をします。
プログラム
- Start関数内で音楽ファイルの長さを取得。
- 基本的にaudioSourceの関数で取得できる長さは秒単位なので関数Strで分+秒表記に変更する。
using UnityEngine; using UnityEngine.UI; public class TimeLineController : MonoBehaviour { [SerializeField] Text text; [SerializeField] Slider slider; float length; string Str(float length) { int min = (int)length / 60; int sec = (int)length % 60; return $"{min}:{sec.ToString("D2")}"; } private void Start() { //曲の全体の長さを取得 length = MusicController.I.audioSource.clip.length; } void Update() { //現在の再生個所を表示 float nowTime = MusicController.I.audioSource.time; //テキスト表示 text.text = $"{Str(nowTime)}/{Str(length)}"; //スライダーの設定 slider.value = nowTime / length; } }
6. 再生速度の制御(⑦SpeedText、⑧SpeedSlider)
「SpeedController.cs」を用意してプログラムを記述して「MusicController」オブジェクトにアタッチし設定をします。
プログラム
- SpeedSliderの値が再生速度の倍率を示すようにするので最小値と最大値をデフォルトの0~1ではなく0.3~3に変更。
- Sliderの値が変更されたときに行う関数onValueChangedはインスペクター上でも設定できるが、今回はスクリプトからUnityAction
をAddListnerすることで設定している。 - 再生速度の初期の倍率は1にしたいのでその設定もしている。
- audioSource.pitchを変更することで再生速度の調節を行っている。
using UnityEngine; using UnityEngine.UI; using UnityEngine.Events; public class SpeedController : MonoBehaviour { [SerializeField] Text text; [SerializeField] Slider slider; void Awake() { //スライダーの最大値・最小値を設定 slider.maxValue = 3.0f; slider.minValue = 0.3f; //スライダーの値を変更すると、再生速度を変更してテキストに表示するよう設定 UnityAction<float> action = (float value) => { MusicController.I.audioSource.pitch = value; text.text = $"{value.ToString("F1")}倍"; }; slider.onValueChanged.AddListener(action); //スライダーの値を1.0にする slider.value = 1.0f; } }
7. 音量の制御(⑩VolumeSlider)
「VolumeController.cs」を用意してプログラムを記述して「MusicController」オブジェクトにアタッチし設定をします。
プログラム
- 処理そのものは「SpeedController.cs」に記述したものと似ている。
- audioSource.volumeを変更することで音量の調節を行っている。
using UnityEngine; using UnityEngine.UI; using UnityEngine.Events; public class VolumeController : MonoBehaviour { [SerializeField] Slider slider; void Awake() { //スライダーの最大値・最小値を設定 slider.maxValue = 1.0f; slider.minValue = 0.0f; //スライダーの値を変更すると、再生速度を変更してテキストに表示するよう設定 UnityAction<float> action = (float value) => { MusicController.I.audioSource.volume = value; }; slider.onValueChanged.AddListener(action); //スライダーの値を1.0にする slider.value = 0.5f; } }
その他
以上の工程で完成しますが
- ⑥TimeSliderを変更することで再生位置の変更などをできるようにする
- 再生する音楽を変更できるようにする
など改善の余地はあります。
前者についてはこちらの記事で解説を行っています。
kiironomidori.hatenablog.com