《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所屬軌道的數據