【Unityの練習ゲーム作り 第一弾!】
ガラケーアプリでもヒットした、昔ながらの「糸通しゲーム」をUnityで作っています。
その1 大まかな設計を考えました
その2 糸と針の動作を実装しました
その3 当たり判定を追加しました
その4 スコアカウントとメイン画面,ゲームオーバー画面をつけました
今回は ゲームを面白くするレベルデザインを考えてみます。
難易度調整
難易度調整にはいくつか方法が考えられます。
- 糸の操作性を悪くする
- 針の隙間を小さくする
- 針の速さを上げる
- …
操作性は、プレイヤーに不快感を与えないギリギリのところに設定する必要があります。かと言って簡単過ぎると、単純なゲームな分 作業的になってしまいます。
実際に自分で試して、最適な値に設定します。
針の種類を増やす
1.幅の小さい針
幅の小さい針をクリアした際には 得られるスコアをアップし、単に難易度を上げるだけにはしないようにします。
2.透明になる針
アニメーションを使用し、透明になる針を作りました。最高難易度の針とします。
・・・
「通常針」,「幅の小さい針」,「透明になる針」をランダムに出現させるようにします。以下のコードでは、3種は等確率に出現します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class HariGenerator : MonoBehaviour { public GameObject hariPrefabRED; public GameObject hariPrefabBLUE; public GameObject hariPrefabVANISH; float span = 3.0f; float delta = 0; // オブジェクト参照 private GameObject gameManager; void Start(){ gameManager = GameObject.Find("GameManager"); } void Update () { this.delta += Time.deltaTime; int kind = UnityEngine.Random.Range(0,2); if(this.delta > this.span){ this.delta = 0; //針の種類切替 int py = Random.Range(-4,4); int hariKind = Random.Range(0,3); switch(hariKind){ case 0: GameObject hariMoveRED = Instantiate(hariPrefabRED) as GameObject; hariMoveRED.transform.position = new Vector3(10, py, 0); break; case 1: GameObject hariMoveBLUE = Instantiate(hariPrefabBLUE) as GameObject; hariMoveBLUE.transform.position = new Vector3(10, py, 0); break; case 2: GameObject hariMoveVanish = Instantiate(hariPrefabVANISH) as GameObject; hariMoveVanish.transform.position = new Vector3(10, py, 0); break; } } } } |
難度の高い針には、高スコアを与えます。今回はそれぞれの針に、タグを付けて実装することにしました。タグの種類によって ThreadeHari(
)
の引数変えて、スコアを変化させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class HariController : MonoBehaviour { private GameObject gameManager; private GameObject itoController; void Start () { gameManager = GameObject.Find("GameManager"); itoController = GameObject.Find("ito"); } void Update () { //フレームごとに等速で移動 transform.Translate(-0.05f,0,0); //画面外に出たらオブジェクトを破壊する if(transform.position.x < -10.0f){ Destroy(gameObject); } //針が特定位置に到達したら、糸が通過したと見なす if(transform.position.x < -3.65f && transform.position.x > -3.7f && gameManager.GetComponent<GameManager>().getFlg()==0 ){ if(this.gameObject.tag == "hariRED"){ gameManager.GetComponent<GameManager>().ThreadeHari(1); } else if(this.gameObject.tag == "hariBLUE"){ gameManager.GetComponent<GameManager>().ThreadeHari(2); } else if(this.gameObject.tag == "hariVanish"){ gameManager.GetComponent<GameManager>().ThreadeHari(3); } } } } |
GameManagerのThreadeHari(
)
も書きかえ、引数の値をスコアにプラスします。
1 2 3 4 5 |
//糸が針通過でスコア更新 public void ThreadeHari(int scoreUp){ score += scoreUp; RefreshScoreText(); } |
こんな感じになりました。(注:更新スコアは上のコードと異なっています。)
針の出現確率を変える
上のコードでは3種の針の出現確率は同じでしたが、後半になるほど高難度の針が出現しやすくなるようにします。
スコアによって針の出現確率を変えます。スコアと出現確率の相関は以下のようにしました。
- ~10 :(通常,幅小,透明)=(80, 20, 0[%])
- ~20 :(通常,幅小,透明)=(60, 20, 20[%])
- ~40 :(通常,幅小,透明)=(40, 40, 20[%])
- ~70 :(通常,幅小,透明)=(20, 40, 40[%])
- ~100:(通常,幅小,透明)=( 0, 60, 40[%])
- 100~:(通常,幅小,透明)=( 0, 40, 60[%])
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class HariGenerator : MonoBehaviour { public GameObject hariPrefabRED; public GameObject hariPrefabBLUE; public GameObject hariPrefabVANISH; private float span = 3.0f; private float delta = 0; private int score =0; private int[] scoreArray; // オブジェクト参照 private GameObject gameManager; void Start(){ gameManager = GameObject.Find("GameManager"); scoreArray = new int[] {1,0,0,0,0}; } void Update () { this.delta += Time.deltaTime; int kind = UnityEngine.Random.Range(0,2); if(this.delta > this.span){ this.delta = 0; //針の種類切替 int py = Random.Range(-4,4); //int hariKind = Random.Range(0,3); score = gameManager.GetComponent<GameManager>().getScore(); if (score >= 10 && score < 20){ scoreArray[3] = 2; }else if (score >= 20 && score < 40){ scoreArray[1] = 1; }else if (score >= 40 && score < 70){ scoreArray[4] = 2; }else if (score >= 70 && score < 100){ scoreArray[2] = 1; }else if (score >= 100){ scoreArray[2] = 2; } int selectKind = Random.Range(0,5); int hariKind = scoreArray[selectKind]; switch(hariKind){ case 0: GameObject hariMoveRED = Instantiate(hariPrefabRED) as GameObject; hariMoveRED.transform.position = new Vector3(10, py, 0); break; case 1: GameObject hariMoveBLUE = Instantiate(hariPrefabBLUE) as GameObject; hariMoveBLUE.transform.position = new Vector3(10, py, 0); break; case 2: GameObject hariMoveVanish = Instantiate(hariPrefabVANISH) as GameObject; hariMoveVanish.transform.position = new Vector3(10, py, 0); break; } } } } |
最初 配列 scoreArrayには、(1,0,0,0,0)が入っています。スコアが増えると配列中の0が、1, 2に更新されていきます。(39~49行目)
そして51,52行目で、配列の中からランダムに1要素を選択し、出現する針を変えています。
イメージはこんな感じ。
BGMをつける
その3で、ミスで爆発SEをつけたときと同じ要領で、針通過ごとにSEを付けていきます。クリアして爽快感を与えるSEが良いですね。
ゲーム全体にもBGMを付けます。Main Cameraにアタッチ!
完成!!
できました!Unity roomで公開しています(画像リンク)。是非一度遊んでみてくださいね。
所感
「糸通し」で使用したコードは、ほぼ参考書内容を改変して作りました。
本を読んてコードを写経しただけでは、全く身になっていませんね。簡単のものでも自分で作ってみることで、自身の技術になることを痛感しました。
その3の「衝突時にエフェクト」と、今回の「後半になるほど難度が上がる」は自分で考えて実装してみました(探せばどこかにはありそうですけど…)。作っていく内に なんとなく「こうすれば できそうかな」というのが、思い浮かんできます。
私のやり方は最良の方法ではないでしょう。
しかし、やりたいこと ⇨ Unityで実現するにはどうするか を考える
Unityに限らず、プログラムを学ぶ上で この蓄積が大事なんだと思います。
・・・
それでは、ここまでお付き合い頂きありがとうございました。
次は、モ◯ストっぽいゲームを作ってみようと考えています。乞うご期待(?)