← 筆記

《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

秒數與拍子

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

  • 變速曲目的秒數拍子轉換規則

    • 設有連續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拍
            • 假設要得到第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拍
        • 在本書的例子中,共有兩款notes:長條和單點
          • 對於單點而言,它只需要知道玩家點撃鍵與其判定時間的時間差即可,單位為拍
          • 對於長按而言,則需要知道玩家點撃鍵與判定線的時間差(起點)以及玩家抬起鍵與判定線的時間差(終點)。
          • 兩種notes正如前面所言,其自身判定時與曲目播放時間將會通過拍數來進行對齊,因為時機的單位為「拍子」
          • 除了時機的數據以外,還需要記錄notes所屬軌道的數據