書籍資訊

  • 書名:《Unityで作るリズムゲーム》
  • 作者:長崎大学マルチメディア研究会

這一篇在講什麼

第一篇把畫面與軌道結構先定下來之後,下一步就是回答一個更核心的問題:

「畫面上的 Note 位置,到底怎麼和譜面時間對上?」

這一篇主要處理三件事:

  • Single Note 的 y 座標到底代表什麼
  • 秒數與拍子怎麼互相換算
  • 如果曲子有變速,這套換算要怎麼擴充

Single Note 的 y 座標其實是在表示時間差

對 Single Note 來說,x 座標代表它屬於哪一條軌道,這一點比較直觀。真正重要的是 y

這裡的 y 並不是單純在表示畫面高度,而是在表示:

Note 應該到達判定線的時間 - 曲目目前已經經過的時間

也就是說,y 本質上是「它離判定點還差多少」的視覺化結果。

如果某個 Note 會在曲目開始後 3 秒打到判定線,那麼:

  • 曲目剛開始時,它的 y 會是正值
  • 到第 3 秒時,它的 y 會等於 0
  • 超過第 3 秒之後,它的 y 會變成負值

如果把:

  • Note 判定時間記成 j
  • 曲目目前時間記成 p

那麼這顆 Note 的 y 可以寫成:

j - p

例如:

  • j = 3, p = 0,所以 y = 3
  • j = 3, p = 3,所以 y = 0
  • j = 3, p = 4,所以 y = -1

為什麼一定要談拍子和秒數

Unity 執行遊戲時,最容易直接取得的是「秒數」;但 BMS 這類譜面格式,真正記錄的通常是「拍子上的位置」。

所以系統一定要能在這兩個量之間互相轉換:

  • 譜面資料習慣用拍子
  • 遊戲播放與音訊同步習慣用秒數

這也是節奏遊戲實作裡很常見的一個分工:

  • 譜面層保存拍點資訊
  • 播放層負責把當前時間換成對應拍點

固定 BPM 下的換算

先看最單純的情況。

  • 1 beat 可以先理解成一個四分音符
  • BPM 表示每分鐘有幾拍

因此每秒有幾拍,其實就是:

BPM / 60

於是:

  • beat = sec * (BPM / 60)
  • sec = beat / (BPM / 60)

例子

如果 BPM = 60

  • 每秒 1
  • 3 秒 = 3
  • 3 拍 = 3

如果 BPM = 120

  • 每秒 2
  • 3 秒 = 6
  • 3 拍 = 1.5

變速曲的關鍵在於分段累加

真正有難度的是曲中變速。

假設一首歌在不同拍段有不同 BPM:

  • 0 - 2 拍與 4 - 6 拍是 60 BPM
  • 2 - 4 拍與 6 - 8 拍是 120 BPM

這時候就不能再用一條公式一次算到底,而是要先判斷目標位置落在哪一個速度段裡,再把前面所有段落累加起來。

拍子轉秒數

例如要算某一拍發生在第幾秒:

  1. 先把它前面完整經過的 BPM 段逐段換成秒數。
  2. 再補上它在當前段內所經過的那一小段。

像前面的例子:

  • 到第 2 拍為止共經過 2 sec
  • 到第 4 拍為止共經過 3 sec
  • 到第 7 拍為止共經過 5.5 sec

秒數轉拍子

反過來要從秒數求拍子時,思路也一樣:

  1. 先累積完整經過的速度段。
  2. 找到目前秒數落在哪一段裡。
  3. 再用該段 BPM 去補出最後那一小段拍數。

對譜面資料來說,最後需要保存什麼

回到節奏遊戲本體,這些換算最後會回到 Note 資料結構上。

系統真正需要知道的資訊,其實很集中:

  • 這顆 Note 在哪一條軌道
  • 這顆 Note 應該在第幾拍被打到
  • 如果是 Long Note,它從哪一拍開始、哪一拍結束

換句話說:

  • 單點 Note 至少要知道判定拍點與軌道
  • 長押 Note 還要再多保存結束拍點

這些就是後面設計 NotePropertyBeatMap 之類類別時的基礎。

我自己的整理

節奏遊戲常讓人一開始就想著「怎麼讓 Note 掉下來」,但其實更重要的是先想清楚:

畫面位置到底是由什麼數學關係推回來的。

這一篇的核心,就是把 y 座標重新理解成「時間差」而不是「高度」。一旦這個觀念成立,很多問題都會自然簡化:

  • 為什麼 Note 會往下走
  • 為什麼它會在某個時刻剛好碰到判定線
  • 為什麼 BPM 一變,整體流動節奏就必須重算

先記住的重點

  • Note 的 y 座標,本質上是在表示它和判定時間之間的差距。
  • 譜面通常記拍子,遊戲執行通常拿秒數,所以一定要做雙向換算。
  • 固定 BPM 可以直接換算,變速曲則必須分段累加。
  • Long Note 需要同時保存起點與終點時間資訊。