【Unity】サウンドテスト画面を作る - その3
Unityでサウンドテスト画面を作る第3回です。
マウスやタッチ操作でなく、キーボードやゲームパッドで動作させるクラシックタイプにアプローチします。
今回は「再生中のBGMタイトル表示」の機能を作っていきます。
そしてこの機能は2つのプロセスを提案してみます。
前回はこちら。 amayoshitqs.hatenablog.com
UI配置
- 「NowPlaying:」と固定表示するText
- 曲名を表示するText
の2つのオブジェクトで構成します。
パターンA・enumそのまま
BGMリストのenum名(ファイル名)をそのまま文字列変換して表示します。
超簡単ですが柔軟性がなく、空白などを入れることもできません。
まずはメンバ変数。
[SerializeField] Text nowPlayingTitleText;
Hierarchyの「NowPlayingTitle」オブジェクトを参照する変数です。
続いてStart()メソッド。
void Start() { nowPlayingTitleText.gameObject.SetActive(false); // 追加 bgmLength = Enum.GetNames(typeof(BgmList)).Length; bgm.maxValue = bgmLength; bgm.minValue = -1; seLength = Enum.GetNames(typeof(SeList)).Length; se.maxValue = seLength; se.minValue = -1; OnChangeBGM(0); OnChangeSE(0); eventSystem.SetSelectedGameObject(bgm.gameObject); }
シーン遷移直後はBGMが再生されていないので曲名を隠すようにします。
今回はオブジェクトを非アクティブにすることにしました。
お次はUpdate()メソッド。
void Update() { var current = eventSystem.currentSelectedGameObject; if(current != go) { OnChangeMenu(current); go = eventSystem.currentSelectedGameObject; } if(Input.GetKeyDown(KeyCode.Z)) { if(current == bgm.gameObject) { BgmList music = (BgmList)bgm.value; bgmSource.clip = Resources.Load<AudioClip>("Audio/" + music.ToString()); bgmSource.Play(); nowPlayingTitleText.gameObject.SetActive(true); // 追加 nowPlayingTitleText.text = music.ToString(); // 追加 } else if(current == se.gameObject) { SeList sound = (SeList)se.value; AudioClip clip = Resources.Load<AudioClip>("Audio/" + sound.ToString()); seSource.PlayOneShot(clip); } else if(current == exit.gameObject) { bgmSource.Stop(); SceneManager.LoadScene("Title"); } } }
BGM再生時にゲームオブジェクトをアクティブにし、曲名を代入します。
enumをToString()でそのまま文字列に変換しています。
まぁ既にResources.Loadで同じことしてますけど。
はい、なんと以上です。
パターンA完成
曲を再生するごとにNowPlaying:の横の文字が切り替わります。
至極簡単に実装できましたが、やはりファイル名として適した名前しか使えないのは不便ですね。
「Hello World」みたいにスペースを含めたり、
「地上コース」みたいな日本語を使うのも難しくなります。
では、曲ごとに固有のタイトルを付けられるようにしましょう!
パターンB・辞書を作って固有定義
C#のDictionaryを使って1曲1曲名前を付けましょう。
前回最後に作った「SoundConstants.cs」のSoundConstantsクラスで定義していきます。
public static class SoundConstants { public static readonly Dictionary<BgmList, string> BgmDictionary = new Dictionary<BgmList, string>() { { BgmList.BGM00, "Queen" }, { BgmList.BGM01, "炎のロックンロール" }, { BgmList.BGM02, "Keep Yourself Alive" } }; }
このように「BgmListとstringのDictionary」を作り、それぞれに個別で文字列を定義していきます。
どこからでも参照できるようにstaticでpublicなクラスおよび変数にする必要があります。
曲名が書けたら「SoundManager.cs」のUpdate()メソッドを修正しましょう。
// nowPlayingTitleText.text = music.ToString(); // 修正前 nowPlayingTitleText.text = SoundConstants.BgmDictionary[music]; // 修正後
辞書を参照して曲名を表示するようにしました。
パターンB完成
このようになりました。
これなら空白も日本語も使い放題です。
ここから曲を再生してない時は「NowPlaying:」も消したい、などの改良はお好みでお願いします。
余談(雑談)
今回で必要最低限の機能が揃ったと思います。
フリー素材ならともかく、オリジナルの楽曲を使用しているゲームでサウンドテストを作るならここまでは欲しいですね。
残りはBGMとSEそれぞれのボリューム調節でしょうか。
機能的にもSliderの真価発揮ですね!
勿論AudioMixer経由での実装を行います、サウンドテストだけのボリューム調節じゃ意味無いですからね!
今回のソースコード
SoundManager.cs
using System; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.SceneManagement; using UnityEngine.UI; public class SoundManager : MonoBehaviour { [SerializeField] EventSystem eventSystem; [SerializeField] Slider bgm; [SerializeField] Text bgmText; [SerializeField] Text bgmNumberText; [SerializeField] Slider se; [SerializeField] Text seText; [SerializeField] Text seNumberText; [SerializeField] Slider exit; [SerializeField] Text exitText; [SerializeField] Text nowPlayingTitleText; // 追加 [SerializeField] AudioSource bgmSource; [SerializeField] AudioSource seSource; int bgmLength; int seLength; GameObject go; void Start() { nowPlayingTitleText.gameObject.SetActive(false); // 追加 bgmLength = Enum.GetNames(typeof(BgmList)).Length; bgm.maxValue = bgmLength; bgm.minValue = -1; seLength = Enum.GetNames(typeof(SeList)).Length; se.maxValue = seLength; se.minValue = -1; OnChangeBGM(0); OnChangeSE(0); eventSystem.SetSelectedGameObject(bgm.gameObject); } void Update() { var current = eventSystem.currentSelectedGameObject; if(current != go) { OnChangeMenu(current); go = eventSystem.currentSelectedGameObject; } if(Input.GetKeyDown(KeyCode.Z)) { if(current == bgm.gameObject) { BgmList music = (BgmList)bgm.value; bgmSource.clip = Resources.Load<AudioClip>("Audio/" + music.ToString()); bgmSource.Play(); nowPlayingTitleText.gameObject.SetActive(true); // 追加 // nowPlayingTitleText.text = music.ToString(); // 修正前 nowPlayingTitleText.text = SoundConstants.BgmDictionary[music]; // 修正後 } else if(current == se.gameObject) { SeList sound = (SeList)se.value; AudioClip clip = Resources.Load<AudioClip>("Audio/" + sound.ToString()); seSource.PlayOneShot(clip); } else if(current == exit.gameObject) { bgmSource.Stop(); SceneManager.LoadScene("Title"); } } } void OnChangeMenu(GameObject current) { bgmText.color = current == bgm.gameObject? new Color(0, 0, 0, 1) : new Color(0, 0, 0, 0.5f); bgmNumberText.color = current == bgm.gameObject? new Color(0, 0, 0, 1) : new Color(0, 0, 0, 0.5f); seText.color = current == se.gameObject? new Color(0, 0, 0, 1) : new Color(0, 0, 0, 0.5f); seNumberText.color = current == se.gameObject? new Color(0, 0, 0, 1) : new Color(0, 0, 0, 0.5f); exitText.color = current == exit.gameObject? new Color(0, 0, 0, 1) : new Color(0, 0, 0, 0.5f); } public void OnChangeBGM(float value) { if(value == bgmLength) { bgm.value = 0; } if(value == -1) { bgm.value = bgmLength-1; } bgmNumberText.text = bgm.value.ToString("00"); } public void OnChangeSE(float value) { if(value == seLength) { se.value = 0; } if(value == -1) { se.value = seLength-1; } seNumberText.text = se.value.ToString("00"); } }
SoundConstants.cs
using System.Collections.Generic; public enum BgmList { BGM00, BGM01, BGM02 } public enum SeList { SE00, SE01, SE02 } public static class SoundConstants { public static readonly Dictionary<BgmList, string> BgmDictionary = new Dictionary<BgmList, string>() { { BgmList.BGM00, "Queen" }, { BgmList.BGM01, "炎のロックンロール" }, { BgmList.BGM02, "Keep Yourself Alive" } }; }