
小学生理論
取りあえず自分の周りの不都合な出来事はオリンピックの所為にしとけば良いと思っている皆さんこんにちは。きっと私の給料が上がらないも彼女ができないのも四連休後の月曜日がひどく憂鬱なのもオリンピックの所為に違いありません。まぁ、でも「オリンピックは開催されるのにロックフェスは~、子供の運動会は~、週末の飲み会は~」とか言っている割に平然と繁華街に出かけて夏休みの旅行プランとか計画している人は記憶障害か何かだと思います。自分以外の誰かが我慢して閉じこもれば良いって事なんでしょうね。
Koreographerというアセット
Unityのアセットで「Koreographer」という結構高額なアセットがあります。これは音楽と同期してイベントを発行してくれる、というアセットで、このブログでもずっと以前に取り上げています。
イベントの設定は音源の波形が表示された専用のエディタを使用するのですが、こちらは音源のBPMに合わせたグリッド線に沿って設定するので、一定のリズムでイベント発行させたい場合にはかなり使い勝手が良いものとなっています。
白い線がグリッドで1ビートの間隔を表しています。上の図では4ビート(1小節)単位に太い線が引かれています。
逆に時間を指定してのイベント発行(曲開始から〇秒後にイベント発行等)には対応していないので、一般的なノーツが振ってくるような音ゲーを作ろうとした場合、画面をタップして欲しいタイミング=音が鳴るタイミングは設定できても、そこから〇秒前に遡ったノーツを生成するタイミングを設定するのには非常に不向きです。
以前、このアセットを使用したゲームを制作した時にはBPMから1ビートの時間を計算し、そこから逆算してイベント発行タイミングを設定していたので一曲分フルで設定しようとするとかなり面倒で手間のかかる作業でした。
今回はその手間を省いて「画面をタップして欲しいタイミング=音が鳴るタイミング」を設定するだけで〇秒前に遡ったノーツを生成するタイミングを計る手順を確立したので、(忘れないように)備忘録として記事に書きたいと思います。Koreographerとか興味ない方はごめんなさい。
事前処理
結論から先に書くと、「Update内でノーツを生成するタイミングを計る」という事になるのですが、これを行うために事前の処理が必要となります。
上の図の赤い線の箇所が「画面をタップして欲しいタイミング」でイベント発行時の引数にはInt型の値を設定しています。
これらのイベントの設定は楽曲毎にKoreographerで作成されるKoreographerphyというコンポーネント内にイベント毎にKoreographyEventクラスとして情報が保持されているので、Start関数等の初期処理でこのKoreographyEventクラスを全てList等に取得しておきます。
Updateでの処理
KoreographyEventクラスにはイベントの発行位置をStartSampleプロパティに保持しています。
これは上のエディタ画面の「Start Sample Location」の値で「曲開始からの時間」にサンプリングレート(KoreographyのSampleRateプロパティ)を掛け合わせた値を示しています。(以降、サンプルタイムと呼ぶ)
この仕様に合わせて、ノーツを生成する為のオフセット時間にサンプリングレートを掛けた値をオフセット値として求めて
Update内で現在のサンプルタイムにオフセット値を加算した値とKoreographyEventクラスのStartSampleプロパティを比較することでノーツを生成するタイミングをチェックします。
説明はちょっと分かりづらいですが、ソースを見れば単純なロジックで実装できることが分かると思います。
使用例
Koreographerには上記の手法で作成された音ゲーがサンプルとして付属していますが、見栄え的には出来が良くないので自前で作ってみました。
飛んでいる鳥の前に障害物が出現、それを避ける場所にターゲットが表示されるのでノーツがそこへ移動したら画面をタップして鳥を移動させます。

gifファイルで音が出せないので、右横の〇が色が変わるタイミングが「音が鳴るタイミング」だと思ってください。
ノーツが移動するタイミイグ = 〇の色が変わるタイミングになっていると思います。
やっぱり面倒くさいな・・・・