読者です 読者をやめる 読者になる 読者になる

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);

    }
}

友人に自作したパズルアプリをプレイしてもらいました

f:id:developer_RYO:20151108150851p:plain

 

 

8パズルで、最短手順を表示しながら遊べる

アプリを勉強用に作っていたのですが、ゲーム好きで同人活動も行なっている

友人にさっと見てもらいました。

 

作ったことに対してすごい!と褒められた一方、もっとこうしたほうがいいよ

という意見もいただきました。

 

・最短手順のヒントがないバージョンも入れる。

・ヒントの表示は、矢印等の記号を入れて直感的に分かりやすくする。

・BGMをバージョンに合わせる。例えば最短手順を見ながら

練習するようなモードであれば、トレーニングしてる感じのBGM、

単純な8パズルを行うのであれば知的な感じを得られるBGMにすると良いとのこと。

 

ヒントなしのバージョンは、作るのが面倒くさくて放置してたのですが、

手を抜いたところというのはユーザーに見抜かれるようです。

BGMについては、DTMで作成したのですが、これまた練習が必要そうです。

 

 

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

こんばんは。


昨日は、音符データを格納する構造体を作成しましたが、結局
後から関数とか新しい変数とか加えそう、という理由でクラスにして、再度作成し直しました。

ネット上では、バイト数とかの容量が小さく、かつ大量に作る場合
構造体の方がいい場合があるという書き込みが幾つかあったけど、
手戻りが走ったときのリスクが大きいのではないか、と思いクラスにしました。


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;
	}
}

音符データの構造体を目をこすりながら作った

こんばんワン。


本日は、作成中の音ゲーについて、音符にどのようなデータがあればいいかどうかを考えた。
コードについては、こちらのサイト
■音ゲーをつくろ~ ♪(^^)♪
を参考にして、考えておりました。

作ろうとしている音ゲーでは、音符の属性なんかを入れようと思っています。
イメージとしては、音符を低音、高音、中音みたいに属性分けして、
低音モードのボタンを押しながら、低音の音符をタップすると、コンボカウントが+2されるようなものです。
(ギターのようなイメージかな?)

サイトを参考に、構造体にしたのですが、もしかしたらクラスにするかもしれません。これ、どっちがいいのだろう。

//音符のデータを構造体にする。
struct Note
{
	//曲が開始してから、いつ入力したら正なのかのタイミングデータ
	float eTime;
	//何小節目か
	byte barNumber;
	//音符の属性
	byte noteType;
}

音符を作成する、作成した音符を移動させるスクリプトを作った。

こんばんは。

 

現在、Unityで音ゲーを作ろうとしているのですが、昨日スクリプトを書いたので、

UPしておきます。

・スペースキーを押すとCubeが生成(後で、音符を生成するタイミングデータと、経過時間を比較して音符を生成するようにしたい。)
・生成後の音符に速度を持たせる(速度については、曲の速さ、画面の大きさによって決定すること。)
 
とりあえず眠いので、お休みなさい。

//音符を作るスクリプトです。

using UnityEngine;

public class CreateNote : MonoBehaviour {
	
	//作成する音符のプレファブ
	public GameObject note;

	void Start () {
	
	}
	
	void Update () {
		
		//もしマウスクリックしたら、音符作成
		if(Input.GetKeyDown(KeyCode.Space))
		InstanceNote();			
	}
	
	//音符を作成する関数
	//引数には音符の色、などを本当は指定。
	void InstanceNote()
	{
		//音符をインスタンス。unityのinstantinate?は処理的に重いので、
		//いつか軽くできるような仕組みを作ること。(awakeで作ったものを瞬間移動させて持ってくるとか)
		Instantiate(note,transform.position,transform.rotation);
	}
	//BMPがある、音データ(いつ鳴らすのか)のデータがある、
	//←いつ作成するかの時刻←(音符作成時から鳴らすまでの時刻)+(ゲームが始まってから音符作成時までの時刻)
	//←音符作成時から、鳴らすまでの時刻はBPM、作成場所からタップ部の距離を使って算出できる
	//←いつ鳴らすのか、という時間から、音符作成から鳴らすまでの時間を差し引けば、いつ音符を作ればいいかがわかるはず。
}
//音符に速度を持たせるためのスクリプトです。

using UnityEngine;
[RequireComponent(typeof (Rigidbody))]

public class MovingNote : MonoBehaviour {

	// Use this for initialization
	void Start () {
		
		//速度の初期化。
		Vector3 noteVelocity = new Vector3(3,0,0);
		this.GetComponent<Rigidbody>().velocity = noteVelocity;
	
	}
	
	
	void Update () {
		//もし、音符がタッチされたり、右に行き過ぎたりしたら、
		//音符を削除。if文の中を変更する。
		if(transform.position.x >= 0)
		{
			Destroy(this.gameObject);
		}
	}	
}

ブログを開設致しました。

こんにちは。

RYOと言います。

 

このブログは、個人開発のログ用に作成しました。

 

スマホアプリやPCゲームの開発を中心に、

・学んだことの記録

・プログラミングでハマったことと、どうやってそれを解決したか

・完成した開発物の公開

などを書いていく方針です。

 

皆さんよろしくお願い致します。