LoginSignup
23
28

More than 5 years have passed since last update.

Unityで音ゲーのアルゴリズム・制作の際気をつけること

Last updated at Posted at 2018-08-22

制作とアルゴリズム編

譜面制作

譜面はCSVファイルやJsonファイルなどのテキストファイルを用いてつくります。
制作する音ゲーに合わせた譜面制作ツールを自作するのが望ましいですが、手っ取り早く済ませたい場合はsetchi氏の「NoteEditor」がオススメです。

NoteEditor紹介ページ(HatenaBlog)

直感でノーツを置けて、できた譜面はJsonファイルとして出力してくれます。

譜面を読み込む

できた譜面を音ゲーで読み込むには、例えばJson形式なら
OtogeFumen fumen = new OtogeFumenでノーツの生成に必要な変数を持ったクラス、OtogeFumenのインスタンス(実体)を作っておき、

fumenjson = Resources.Load<TextAsset>("パス").ToStringでJsonファイルの中身をstring型で受け取って、

JsonUtility.FromJson<OtogeFumen>(fumenjson)を使って作ったインスタンスに値を反映します。

その後はfumen.notestype[i]などで必要な情報を使うわけですね。

詳しくはLemontea氏が分かりやすくまとめてくれています。

Unity Json形式とファイルへの書き出し・読み込み

譜面制作ツールを自作する際、必要な値は?

譜面制作ツールを自作する場合、先ほどの「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は「自分自身」には使えないので、他のオブジェクトにアタッチしたスクリプトから実行しましょう。

音ゲー制作で気をつけることはこれくらいです。

ひとこと

音ゲーは簡単なものであれば計算は算数の知識だけで済みます。
その分演出をどれだけ凝るかというものなので、気になったものはどんどん検索して、知識を吸収・ゲームに反映しましょう!

23
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
28