【Unityの練習ゲーム作り 第一弾!】
ガラケーアプリでもヒットした、昔ながらの「糸通しゲーム」をUnityで作っています。
その1 大まかな設計を考えました
その2 糸と針の動作を実装しました
今回は 糸,針に当たり判定をいれ、ゲームオーバーになる処理を作ります。
当たり判定
Rigidbodyを使うと、糸と針を衝突させるのはとっても簡単。判定エリアに適当にいじって、以下のように両者が当たるようになりました。
今回は両者が当たった瞬間ゲームオーバーとなりますが、↑図のような挙動は 他のゲームで応用できそうですね。
続いて、「糸と針が衝突したことを検知する」命令を、糸の動作を制御する、ItoContorellrスクリプトに追加します。
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ItoController : MonoBehaviour { Rigidbody2D rigid2d; float antiGravity = 175.0f; // Use this for initialization void Start () { this.rigid2d = GetComponent<Rigidbody2D>(); } // Update is called once per frame void Update () { //Spaceが押されている間上昇する if(Input.GetKey(KeyCode.Space)){ //Debug.Log("押している"); this.rigid2d.AddForce(transform.up * this.antiGravity); } } //糸が針に当たった void OnTriggerEnter2D(Collider2D other){ Debug.Log("触れた"); if(other.gameObject.tag == "hari"){ Debug.Log("触れた hari"); Destroy(gameObject); GameObject GameManager = GameObject.Find("GameManager"); GameManager.GetComponent<GameManager>().GameOver(); } } } |
今回は衝突検知に、OnTriggerEnter2D(Collider2D)
を使用しています。リファレンスの記述の通り、「オブジェクトにアタッチしたトリガーの中に別のオブジェクトが入ったときに呼び出されます。」そのため、isTriggerをオンにすることを忘れずに。
針にはTag「hari」をつけ、衝突時にオブジェクトが針であることを認識するようにしています。
糸通しでは 糸と針しかオブジェクトがないため、あまり意味がありません。敵を区別する場合 等に使うのでしょうか?ぷよぷよのようなパズルで、色を識別するのにも使用できそうです。Tagを活かしたゲームが次回の課題です。
28行目では 糸が何かのオブジェクトに当たったこと、31行目では「hari」タグをもったオブジェクトに当たったことを確認するため、Debug.Log()
で確認しています。
このあと、33-34行目でGameManager
というオブジェクト内の、GameOver()
を呼び出しています。わたす引数はありません。
今のところ GameManager
には、以下のようにDebug.Log()
だけが記載されています。
1 2 3 4 5 6 7 8 9 10 11 12 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class GameManager : MonoBehaviour { //ゲームオーバー public void GameOver(){ Debug.Log("game over"); } } |
実際に動かしてみます。低画質ですみません・・・。見えづらいのですが、糸が当たった瞬間コンソールに、”触れた”,”触れた hari”,”game over”と出力されます。
糸が他のオブジェクトに当たったこと,針(「hari」タグ)に当たったこと,GameOver()
を呼び出したことが確認できました。
GameOver()
は今後 シーンの遷移に使用する予定です。
表現を付ける
このままでは寂しいので、糸が針に当たった瞬間に、ゲームオーバー表現として 糸が爆発しながら落下するエフェクトを追加します。
今回はこんな方法を使ってみました。
・・・
はじめに、糸にParticle Systemを追加します。Particle SystemのOrder in Layerを調整すると、Particleが見えないようになります。
さて、Particleが見えない状態で 糸を回転させてみます。すると、Particleがまた見えるようになりますね。
Particleの出現方向を利用し、オブジェクトの方向を変えることで Particleの向きも同様に変えています。
これを利用しゲームオーバー表現を作ってみます。ItoContorellrスクリプトに、衝突後 オブジェクトが回転する命令を追加します。
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 ItoController : MonoBehaviour { Rigidbody2D rigid2d; float antiGravity = 175.0f; float rotAngle = 180.0f; // Use this for initialization void Start () { this.rigid2d = GetComponent<Rigidbody2D>(); } // Update is called once per frame void Update () { //Spaceが押されている間上昇する if(Input.GetKey(KeyCode.Space)){ //Debug.Log("押している"); this.rigid2d.AddForce(transform.up * this.antiGravity); } } //糸が針に当たった void OnTriggerEnter2D(Collider2D other){ //Debug.Log("触れた"); if(other.gameObject.tag == "hari"){ //Debug.Log("触れた hari"); transform.Rotate(this.rotAngle*-1.0f,this.rotAngle*0.5f,0); Destroy(gameObject, 2.0f); GameObject GameManager = GameObject.Find("GameManager"); GameManager.GetComponent<GameManager>().GameOver(); } } } |
9行目でrotAngle
を初期値180として新たに定義。33,34行目に以下を追加しました。
1 2 |
transform.Rotate(this.rotAngle*-1.0f,this.rotAngle*0.5f,0); Destroy(gameObject, 2.0f); |
x軸は-180度,y軸は 90度回転させています。y軸を回転させるのは、Particleでの説明の通り。
x軸の回転は、オブジェクトを上下を逆さまにすることで、スペースを押したときに 糸に対し 画面下方向に力をかけるためです。衝突後も ふわふわ動かせたらおかしいですもんね。*衝突後、キー操作を受け付けない でもOKです。
その後、Destroy
で糸オブジェクトを消しています。
こんな感じになりました。
続いて、衝突時の効果音を付けます。効果音ラボ様から「爆発2」をお借りしました。
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ItoController : MonoBehaviour { Rigidbody2D rigid2d; float antiGravity = 175.0f; float rotAngle = 180.0f; public AudioClip bombSE; AudioSource aud; // Use this for initialization void Start () { this.rigid2d = GetComponent<Rigidbody2D>(); this.aud = GetComponent<AudioSource>(); } // Update is called once per frame void Update () { //Spaceが押されている間上昇する if(Input.GetKey(KeyCode.Space)){ //Debug.Log("押している"); this.rigid2d.AddForce(transform.up * this.antiGravity); } } //糸が針に当たった void OnTriggerEnter2D(Collider2D other){ //Debug.Log("触れた"); if(other.gameObject.tag == "hari"){ //Debug.Log("触れた hari"); this.aud.PlayOneShot(this.bombSE); transform.Rotate(this.rotAngle*-1.0f,this.rotAngle*0.5f,0); Destroy(gameObject, 2.0f); GameObject GameManager = GameObject.Find("GameManager"); GameManager.GetComponent<GameManager>().GameOver(); } } } |
衝突時に、効果音を呼び出します。
ゲームオーバー条件を追加
糸が、一定以上 画面からはみ出たときにもゲームオーバーとなるようにします。針の消去と同じ方法で記述。
糸-針の衝突と同様に、糸オブジェクトを破壊し、GameOver()
を呼び出しています。
ただ、糸オブジェクトは慣性で上昇/下降を続け、糸オブジェクトが消えるまでの間、効果音とGameOver()
が連続して呼ばれます。これを防ぐため、一度しか呼び出せれないようflg
を使用しています。
1 2 3 4 5 6 7 |
if((transform.position.y > 10 || transform.position.y < -10) && flg==0){ this.aud.PlayOneShot(this.bombSE); Destroy(gameObject, 2.0f); GameObject GameManager = GameObject.Find("GameManager"); GameManager.GetComponent<GameManager>().GameOver(); flg = 1; } |
flgは、上記の糸 – 針の衝突にも追加しました。
次回は、針を通過した本数をカウントするUI と ゲームオーバー画面とメイン画面を追加していきます。
もう少し!その4に続く