《Unityで作るリズムゲーム》學習筆記(二):「Notes的行動分析」
書名:《Unityで作るリズムゲーム》
作者:長崎大学マルチメディア研究会
Single Note的坐標代表甚麼
- x坐標代表了Note流動的軌道
- y坐標則代表「從曲目開始到Note與判定線重合的時間,與曲目開始到現在的經過時間」之間的「差」
- 這個「差」的意思:比如說有一個Note(noteX)在曲目開始3秒後與判定線重疊,那noteX的y坐標具體變化就可以表示為:
- 曲目開始3秒後,該note的y坐標為0
- 而曲目開始2秒後,該note的y坐標為正值
- 而曲目開始3.1秒後,該note的y坐標為負值
- 設一note的判定時間為 j,曲目開始後經過時間為 p
- 其y坐標為 j - p
- j = 3, p = 0, j - p = 3
- j = 3, p = 3, j - p = 0
- j = 3, p = 4, j - p = -1
- 這個「差」的意思:比如說有一個Note(noteX)在曲目開始3秒後與判定線重疊,那noteX的y坐標具體變化就可以表示為:

秒數與拍子
- 在該教程中的音樂遊戲將會讀取使用BMS格式編寫的文件作為遊戲的「樂譜」
- BMS主要包含了「時機」信息,也就是「這裡需要用這個節奏來演奏」以及「曲目開始後經過多少拍,這條軌道會有notes掉落」的情報
- 但在Unity中,我們只能以秒為單位獲得從曲目開始後所經過的時間。
- BMS主要包含了「時機」信息,也就是「這裡需要用這個節奏來演奏」以及「曲目開始後經過多少拍,這條軌道會有notes掉落」的情報
- 根據前面提到過的,決定一個note的y坐標的條件分別為:「Note與判定線重合的時間」、「曲目開始後到現在經過的時間」,這兩個條件在這部分被分別表述為:
- ノーツが持つ時間(Note本身的時間)
- 本身是拍子數,通過bms格式的檔案獲取
- 曲が始まってからの経過時間(曲目開始後至今的經過時間)
- 本身是秒數,使用Unity獲取
- ノーツが持つ時間(Note本身的時間)
- 這兩個時間單位的獲取是必須的,這裡有兩種途徑可以得到他們:
- 一是「與拍子對齊」
- 也就是將「樂曲的經過時間轉換成拍子」
- 這是本書所使用的方法,也是我所使用的方法
- 二是「與秒對齊」
- 一是「與拍子對齊」
- 秒數與拍子之間的轉換規則
- 秒的單位(1秒 = 1sec)
- 拍的單位(1拍 = 1個四分音符 = 1beat)
- 在音樂遊戲中,存在一個名為「BPM」的概念,其意義為「Beat per minute」,也就是「1分鐘內的拍子數量」的意思
- 因此,如果將BPM / 1分鐘的秒數(60),就可以得出「Beat per second」(1秒內的拍子數量」
- sec : beat = 1 : BPM / 60
- 由此推出:
- beat = sec * (BPM / 60)
- 經過的拍子數 = 經過的秒數 * (每秒的拍子數)
- sec = beat / (BPM / 60)
- 經過的秒數 = 經過的拍子數 /(每秒的拍子數)
- beat = sec * (BPM / 60)
- 假設當前有4個連續的4分音符
- 設BPM = 60,每秒拍子數 = 60/60 => 1秒1拍
- 如經過秒數為3
- 經過拍子數則為( 3 * ( 60/60) ) = 3拍
- 如經過拍子數為3
- 經過秒數則為( 3 / (60/60) ) = 3拍
- 如經過秒數為3
- 設BPM = 120,每秒拍子數 = 120/60 => 1秒2拍
- 如經過秒數為3
- 經過拍子數則為( 3 * (120/60) ) = 6拍
- 如經過拍子數為3
- 經過秒數則為( 3 / (120/60) ) = 1.5拍
- 如經過秒數為3
- 設BPM = 60,每秒拍子數 = 60/60 => 1秒1拍
- 因此,如果將BPM / 1分鐘的秒數(60),就可以得出「Beat per second」(1秒內的拍子數量」

-
變速曲目的秒數拍子轉換規則
-
- 設有連續9拍子 - 0-2、4-6拍的BPM為60 - 2-4、6-8拍的BPM為120

-
-
- 拍子轉秒數
- 到第2拍的經過時間 = (2拍 - 0拍) / (60BPM / 60) = 2 sec
- 到第4拍的經過時間 = (4拍 - 2拍) / (120BPM / 60) = 1 + 2(above) = 3 sec
- 到第5拍的經過時間 = (5拍 - 4拍) / (60BPM / 60) = 1 + 3(above) = 4 sec
- 到第6拍的經過時間 = (6拍 - 5拍) / (60BPM / 60) = 1 + 4(above) = 5 sec
- 到第7拍的經過時間 = (7拍 - 6拍) / (120BPM / 60) = 0.5 + 5(above) = 5.5 sec
- 秒數轉拍子
- Calculate total Beats with given time
- 到第2秒的累積拍子數 = (2秒 - 0秒) * (60BPM / 60) = 2拍
- 到第3秒的累積拍子數 = (3秒 - 2秒) * (120BPM / 60) = 2 + 2(above) = 4拍
- 到第4秒的累積拍子數 = (4秒 - 3秒) * (60BPM / 60) = 1 + 4(above) = 5拍
- 到第5秒的累積拍子數 = (5秒 - 4秒) * (60BPM / 60) = 1 + 5(above) = 6拍
- 到5.5秒的累積拍子數 = (5.5秒 - 5秒) * (120BPM / 60) = 1 + 6(above) = 7拍
- 到第6秒的累積拍子數 = (6秒 - 5秒) * (120BPM / 60) = 2 + 6(above) = 8拍
- Calculate total Beats on specific time with given beat
- 假設要得到第4秒所經過的拍子數
- 第一段變速:到第2拍的經過時間 = (2拍 - 0拍) / (60BPM / 60) = 2 sec
- 第二段變速:到第4拍的經過時間 = (4拍 - 2拍) / (120BPM / 60) = 1 + 2(above) = 3 sec
- 第三段變速:到第6拍的經過時間 = (6拍 - 4拍) / (60BPM / 60) = 2 + 3(above) = 5 sec => 無法得到第4秒的拍子數,第3秒時,累積拍子數為4;第5秒時,累積拍子數為6
- 為了得到第4秒的累積拍子數,需要在第3秒的累積拍子數(4拍)基礎上加上「被跳過的秒數 * 該BPM的段中的每秒拍子數」(sec * (BPM/60))
- 從第3秒到第4秒,共1秒,sec = 1
- 第4拍的段落BPM為60,每秒拍子數為 = 1
- 該拍子所在BPM段的每秒拍子數 = 1 * 1 = 1
- 因此,第4秒的累積拍子數 = 4 + 1 = 5拍
- 為了得到第4秒的累積拍子數,需要在第3秒的累積拍子數(4拍)基礎上加上「被跳過的秒數 * 該BPM的段中的每秒拍子數」(sec * (BPM/60))
- 假設要得到第5.5秒所經過的拍子數
- 已知到第6拍時,經過時間為:
- [第一段速度段(0-2拍)的累計時間] + [第二段速度段(2-4拍)的累計時間] + [第三段速度段(4-6拍)的累計時間]
- => [(2 - 0拍) / (60BPM / 60) = 2] + [(4 - 2拍) / (120BPM / 60) = 1] + [(6 - 4拍) / (60BPM / 60) = 2] = 2秒 + 1秒 + 2秒 = 5秒
- 已知第四個速度段為第6到8拍,而加上第四個速度段的累計時間則為 (8 - 6拍) / (120BPM / 60) = 1秒 + 5秒 = 6秒
- =>無法得知第5.5秒的累積拍子
- 因此需要單獨被跨過的秒數的每秒拍子數
- => 0.5秒 * (120BPM / 60) = 1拍
- 因此,第5.5秒的累積拍子數為6拍 + 1拍 = 7拍
- 因此需要單獨被跨過的秒數的每秒拍子數
- 已知到第6拍時,經過時間為:
- 假設要得到第4秒所經過的拍子數
- Calculate total Beats with given time
- 在本書的例子中,共有兩款notes:長條和單點
- 對於單點而言,它只需要知道玩家點撃鍵與其判定時間的時間差即可,單位為拍
- 對於長按而言,則需要知道玩家點撃鍵與判定線的時間差(起點)以及玩家抬起鍵與判定線的時間差(終點)。
- 兩種notes正如前面所言,其自身判定時與曲目播放時間將會通過拍數來進行對齊,因為時機的單位為「拍子」
- 除了時機的數據以外,還需要記錄notes所屬軌道的數據
- 秒數轉拍子
- 拍子轉秒數
- 到第2拍的經過時間 = (2拍 - 0拍) / (60BPM / 60) = 2 sec
- 到第4拍的經過時間 = (4拍 - 2拍) / (120BPM / 60) = 1 + 2(above) = 3 sec
- 到第5拍的經過時間 = (5拍 - 4拍) / (60BPM / 60) = 1 + 3(above) = 4 sec
- 到第6拍的經過時間 = (6拍 - 5拍) / (60BPM / 60) = 1 + 4(above) = 5 sec
- 到第7拍的經過時間 = (7拍 - 6拍) / (120BPM / 60) = 0.5 + 5(above) = 5.5 sec
-