unityで音ゲーのモックを作りました
音ゲーを作っているのですが、ゲームの大体のロジックをつかみたいと思い、
こちらのサイトを参考にしつつサンプルを作ってみました。
blog.bokuweb.me
方針として、0,1,2,・・・番のタイミングデータとユーザーの入力時間を比較し、
誤差が少なければOK、多ければBADの結果を出力します。
データの持ち方
- 曲開始からの時刻を格納する変数timer
- 曲のタイミングデータを格納する配列timing
- ユーザーの入力に対して、どのタイミングデータを比較するかを指定する変数indexTiming
- 曲の判定結果を格納しておく変数cool,good,bad
処理的なもの
- ユーザーがスペースキー入力したらtrue返すIsBeat()
- 現在のtimerとタイミングデータtimingを比較し、判定結果をcool,good,badに追加していくcheckTiming()
- cool,good,badを+1するadd●●()
ゲームのフロー
ゲーム開始時にタイマーに0を代入し、曲を開始します。
音符(といってもブロック)については、タイミングデータの1秒前に音符を生成していく。速度については生成1秒後にヒットバーに当たるようにする。
ゲーム中はユーザーの入力があればタイミングデータとの比較を行い、判定範囲であれば結果を変数にプラスしていきます。
感想
参考にさせていただいたサイトが非常にわかりやすく、1,2時間ほどでサンプルを作ることができました。ありがとうございます。
音符を消す処理をどうするか、音符を動かすラインが複数ある時の処理、音ズレ対策などまだまだやることがたくさんありますが、
簡単なサンプル作成によって作りたいもののイメージをより強く持つことができました。
ソースコード
ヒットバーのオブジェクトにつけたファイル
using UnityEngine; using System.Collections; public class Beat : MonoBehaviour { //本番作品では、なるべくstatic変数を使わないこと。 //ゲームのタイマーを宣言。 public static float timer; //曲のタイミングデータを宣言 public static float[] timing; //音符のインデックスを宣言。 private int indexTiming; //曲の判定結果を格納しておく変数を宣言。 public static int cool; public static int good; public static int bad; //エフェクトを格納。 public GameObject goodEffect; public GameObject badEffect; //開始時 void Start () { //タイミングデータはDTMを見ながら作成した。 timing = new float[] {1.495f,2.220f,2.580f,2.942f,3.664f,4.387f,4.749f,5.110f,5.472f,5.833f,6.556f,7.279f,7.818f,8.363f,8.725f,9.267f,9.809f,10.170f,10.713f,11.255f,11.616f,11.797f,11.978f,12.158f,12,339f,1000f}; cool = 0; good = 0;bad = 0;indexTiming = 0;timer = 0; } void Update () { if (IsBeat()) checkTiming(); //音符がヒットバーより後ろに流れたときの処理 else if (timer - timing[indexTiming] >= 0.12f) { addBad(); indexTiming++; Instantiate(badEffect, transform.position, transform.rotation); } timer += Time.deltaTime; } //スペースキーで入力。 public bool IsBeat() { if (Input.GetKeyDown(KeyCode.Space)) return true; else return false; } //入力とタイミングデータの比較を行い、スコアを計上していく。 public void checkTiming() { //タイミング誤差の範囲についてはいったんpublicにしてテストしやすくしたほうがいいかも if(timer - timing[indexTiming] >= -0.10f && timer - timing[indexTiming] <= 0.10f) { addCool(); indexTiming++; Instantiate(goodEffect, transform.position, transform.rotation); } else if(timer - timing[indexTiming] >= -0.12f && timer - timing[indexTiming] <= 0.12f) { addGood(); indexTiming++; Instantiate(goodEffect, transform.position, transform.rotation); } else if(timer - timing[indexTiming] >= -0.6f && timer - timing[indexTiming] <= 0.6f) { addBad(); indexTiming++; Instantiate(badEffect, transform.position, transform.rotation); } else { //何もしません。 } //デバッグログ用 //outputResult(); } //結果の追加 public void addCool(){cool++;} public void addGood(){good++;} public void addBad(){bad++;} //デバッグログに結果の出力 //public void outputResult() //{ // Debug.Log("cool=" + cool + "\t" + "good=" + good + "\t" + "bad=" + bad + "\n"); //} }
音符を生成して、初期速度を持たせるファイル
using UnityEngine; using System.Collections; public class CreateNote : MonoBehaviour { //音符オブジェクトを生成するため public GameObject note; //音符の生成位置指定用 public Vector3 position = new Vector3(-10, 0, 0); private int index = 0; void Start() { } void Update () { //スタート時にまとめて作ったほうがカクツキが少なくなるかも if(Beat.timer >= Beat.timing[index] -1) { Create(); index++; } } //音符を作る関数 public void Create() { Instantiate(note, position, this.transform.rotation); } }