制作とアルゴリズム編
譜面制作
譜面はCSVファイルやJsonファイルなどのテキストファイルを用いてつくります。
制作する音ゲーに合わせた譜面制作ツールを自作するのが望ましいですが、手っ取り早く済ませたい場合はsetchi氏の「NoteEditor」がオススメです。
直感でノーツを置けて、できた譜面はJsonファイルとして出力してくれます。
譜面を読み込む
できた譜面を音ゲーで読み込むには、例えばJson形式なら
OtogeFumen fumen = new OtogeFumen
でノーツの生成に必要な変数を持ったクラス、OtogeFumenのインスタンス(実体)を作っておき、
fumenjson = Resources.Load<TextAsset>("パス").ToString
でJsonファイルの中身をstring型で受け取って、
JsonUtility.FromJson<OtogeFumen>(fumenjson)
を使って作ったインスタンスに値を反映します。
その後はfumen.notestype[i]
などで必要な情報を使うわけですね。
詳しくはLemontea氏が分かりやすくまとめてくれています。
譜面制作ツールを自作する際、必要な値は?
譜面制作ツールを自作する場合、先ほどの「fumen」クラスには、
・ノーツが落ちてくるレーン(int型)
・曲が始まってからの時間(float型の配列)
または
・小節の位置(int型の配列)と、BPM(float型)
が必要です。小節位置とは、4分音符が置ける位置に通し番号をつけた、その番号のことです。
ロングノーツ(長押しノーツ)を入れたいなら、
・ノーツのタイプ(通常ノーツかロングノーツか)
・ロングノーツの始点と終点の、曲が始まってからの時間
または
・ロングノーツの始点と終点の小節位置に通し番号を付けたもの
が必要です。
ノーツの座標を計算する
今回は小節位置で計算する方法をとって考えます。x,z方向に平らな平面を想像してください。
z方向にノーツが落ちてくる、4レーンの音ゲーと仮定すると、
x座標はそのまま、ノーツが落ちてくるレーンを記録した変数(int型)をswitchを使って振り分けます。
y座標は変化がないので固定の値です。
z座標ですが、まずは最も細かく通常ノーツを配置したときの間隔(時間)を出します。
60(秒)/(BPM*4)で算出できます。ここでの4は4分音符の4です。
次に、小節位置と、ノーツ間の最短間隔を使ってノーツを押すタイミング(曲が始まってからの時間)を出します。
(小節位置)*(ノーツ間の最短間隔)で算出します。
そして、ノーツを押すタイミングと、ノーツが動く速さ(距離/秒)から、ノーツの座標を出します。
(押すタイミング)*(速さ)です。
しかし、このままでは判定ラインからの相対的な座標になってしまうので、
(ノーツのz座標)+(判定ラインのz座標)
で、World座標にします。
これで、ノーツの座標が計算できました。
判定する
ノーツと判定ラインのCollider衝突判定を使うと、若干の誤差が生まれるうえに、transform.positionをUpdate関数で書き換える方法でノーツを動かしている場合、小さなワープの連続と同じなので衝突判定をすり抜けてしまいます。
なので、基本的には時間で判定します。
Time.timeSincelevelLoad
を使うとシーン読み込みからの時間を取得することができます。
キー押下時の時間を、シーン読み込みからの時間をfloat型の変数に代入することで保存し、判定に使います。
キーが押されたら、そのキーに対応したレーンのノーツをGameObject.FindGameObjectsWithTag
を使って取得し、foreachを使って距離を一つずつ比較し、最終的に判定ラインに最も近いノーツを取得します。
そして、判定ラインに最も近いノーツの、押すべきタイミングを使い、判定します。
キーを押すべきタイミングは「ノーツの座標を計算する」で出したものを使います。
(ノーツの座標を計算する際に配列に詰めておきます)
(押すべきタイミング)-(キー押下タイミング)の絶対値をとり、if elseで振り分けて判定します。
判定は以上です。
気をつけること編
重い処理をしない
Unityの関数の中でもInstantiateやDestroyは非常に重たい関数です。
プレイ中にこれらの関数を使うのは、誤差を著しく嫌う音ゲーにとって好ましくありません。
よって、ノーツの生成はStart関数の中に書きましょう。
また、Destroyの代替として、GameObject.SetActive
を使います。この関数でノーツのオブジェクトを無効化することで、消えたように見せることができます。GameObject.SetActive
は「自分自身」には使えないので、他のオブジェクトにアタッチしたスクリプトから実行しましょう。
音ゲー制作で気をつけることはこれくらいです。
ひとこと
音ゲーは簡単なものであれば計算は算数の知識だけで済みます。
その分演出をどれだけ凝るかというものなので、気になったものはどんどん検索して、知識を吸収・ゲームに反映しましょう!