前提・実現したいこと
初めてUnityで音ゲーを作ろうとしておりますが分かりません...。
まず、試しに曲とテンポがマッチするようにBPMを元にメトロノームを作ろうとしましたが、
どうしてもズレが生じてしまいます。原因はおそらく、Update関数で処理をしているため
不安定な状況になっており、処理がおいついていないのだと思います。
そこで、とあるサイトのソースコードを元に試したところ
完璧に合うようになりました。
しかし、そのコードがどのような仕組みなのか、なぜ合ったのかイマイチ理解できない部分があるので
解説していただけないでしょうか...?また、他に良い方法が何かあれば教えていただけると幸いです..。
発生している問題・エラーメッセージ
曲とテンポにずれが生じてしまう
解説して頂きたいソースコード
C#
1public class GoodMetronome : MonoBehaviour { 2 3 [SerializeField] AudioSource _ring; 4 5 double _bpm = 140d; 6 double _metronomeStartDspTime; 7 double _buffer = 2 / 60d; 8 9 void Start() { 10 _metronomeStartDspTime = AudioSettings.dspTime; 11 } 12 13 void FixedUpdate() { 14 var nxtRng = NextRingTime(); 15 16 if (nxtRng < AudioSettings.dspTime + _buffer) { 17 _ring.PlayScheduled(nxtRng); 18 } 19 } 20 21 double NextRingTime() { 22 var beatInterval = 60d / _bpm; 23 var elapsedDspTime = AudioSettings.dspTime - _metronomeStartDspTime; 24 var beats = System.Math.Floor(elapsedDspTime / beatInterval); 25 26 return _metronomeStartDspTime + (beats + 1d) * beatInterval; 27 } 28} 29
上記ソースコードを参考に作成したソースコード
C#
1using System.Collections; 2using System.Collections.Generic; 3using System.IO; 4using UnityEngine; 5using UnityEngine.UI; 6 7public class GameControl : MonoBehaviour{ 8 9 //譜面情報 10 private List<string[]> SONG_SCORE = new List<string[]>(); 11 private TextAsset SONG_FILE; 12 private string SONG_TITLE; 13 private string SONG_ARTIST; 14 private float SONG_BPM; 15 16 private double _metronomeStartDspTime; 17 private double _buffer = 2 / 60d; 18 private int Count = 0; 19 20 //音楽ファイル 21 private AudioSource[] BGM; 22 23 //譜面情報TEXTオブジェクト 24 private Text[] TITLE_A; 25 26 private bool test = false; 27 28 // Start is called before the first frame update 29 void Start() 30 { 31 //譜面情報を取得する 32 GetGameScore(); 33 34 //テキスト取得 35 TITLE_A = new Text[4]; 36 TITLE_A[0] = GameObject.Find("TITLE").GetComponent<Text>(); 37 TITLE_A[1] = GameObject.Find("ARTIST").GetComponent<Text>(); 38 TITLE_A[2] = GameObject.Find("BPM").GetComponent<Text>(); 39 TITLE_A[3] = GameObject.Find("Beat").GetComponent<Text>(); 40 41 //テキスト編集 42 TITLE_A[0].text = "曲名;" + SONG_TITLE; 43 TITLE_A[1].text = "アーティスト:" + SONG_ARTIST; 44 TITLE_A[2].text = "BPM:" + SONG_BPM; 45 46 //BGMとSEを取得 47 BGM = this.GetComponents<AudioSource>(); 48 49 //開始地点(OFF_SET) 50 BGM[0].time = 0.6f; 51 52 53 //確認用 54 _metronomeStartDspTime = AudioSettings.dspTime; 55 56 57 } 58 59 // Update is called once per frame 60 void FixedUpdate() 61 { 62 63 double nxtRng = NextRingTime(); 64 65 if (nxtRng < AudioSettings.dspTime + _buffer) 66 { 67 if (test == false) { BGM[0].Play(); test = true; } 68 BGM[1].PlayScheduled(nxtRng); 69 } 70 71 } 72 73 //CSVファイルから譜面情報を取得 74 void GetGameScore() 75 { 76 SONG_FILE = Resources.Load("Score/TestMusic") as TextAsset; 77 StringReader reader = new StringReader(SONG_FILE.text); 78 79 while (reader.Peek() > -1) 80 { 81 string line = reader.ReadLine(); 82 SONG_SCORE.Add(line.Split(',')); 83 } 84 85 //TITLE、ARTISを抽出 86 SONG_TITLE = SONG_SCORE[0][0].Replace("TITLE:",""); 87 SONG_ARTIST = SONG_SCORE[1][0].Replace("ARTIST:", ""); 88 SONG_BPM = float.Parse(SONG_SCORE[2][0].Replace("BPM:", "")); 89 } 90 91 double NextRingTime() 92 { 93 double beatInterval = 60d / SONG_BPM; 94 double elapsedDspTime = AudioSettings.dspTime - _metronomeStartDspTime; 95 double beats = System.Math.Floor(elapsedDspTime / beatInterval); 96 97 return _metronomeStartDspTime + (beats + 1d) * beatInterval; 98 } 99 100}
補足情報(FW/ツールのバージョンなど)
Unity 2019.3.3f1
回答1件
あなたの回答
tips
プレビュー