developer_RYO’s blog

スマホアプリやPCゲーム、音楽やイラストを自由気ままに作っている人の技術ログです

unityで音ゲーのモックを作りました

f:id:developer_RYO:20151111222709g:plain

音ゲーを作っているのですが、ゲームの大体のロジックをつかみたいと思い、
こちらのサイトを参考にしつつサンプルを作ってみました。
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);

    }
}

音符のデータを格納するクラス

ClassNote.cs

//音符のデータをクラスにする。
public class Note
{
	//曲が開始してから、いつ入力したら正なのかのタイミングデータ
	private float timingData;
	//何小節目か
	private byte barNumber;
	//音符の属性
	private byte type;
	
	//データのセットはインスタンス化する時に行う。
	Note(float noteTiming,byte noteBarNumber,byte noteType)
	{
		this.timingData = noteTiming;
		this.barNumber = noteBarNumber;
		this.type = noteType;
	}
}