【Unity】ブロック崩し(3D)の制作手順を解説!反射角度・速度調整・クリア判定まで
簡単なゲームの代名詞である、ブロック崩しゲームを一緒に作っていきましょう。
ゲームスタートからゲームクリア、もしくはゲームオーバーまでを一連で作成していくので、「Unityで簡単なゲーム作ってみたい方」は是非お試しください。
記事の内容は初心者の方にもわかるように詳しく解説していますが、ゲームを作成し慣れている人であれば2時間程度で終わるような内容ですのでぜひチャレンジしてみてください。
Contents
概要
これから作るブロック崩しゲームはこんな感じです。(ボールは実際作っていくときはもう少し小さいですが、分かりやすいように大きくしています。)
非常にシンプルな内容になっています。
ではこれをゴールに作成していきましょう。
Projectの新規作成
まずProjectを新規作成しましょう。下の画像のようにProject Nameに「Block Collapse」と入力し、3Dを選択した上でCreate projectをクリックします。
シーンを保存する
Unityではプロジェクトの下にシーンというものが存在し、プロジェクトを構成します。
複数のシーンを遷移することで色々と実現することができますが、詳しい解説は割愛します。
ヒエラルキーウィンドウのSampleSceneを右クリックしてSaveSceneAsを選択してください。次にSaveAs欄に「Game」と入力してSaveを選択します。これでシーンの保存が完了しました。
シーンやこの後出てくるC#スクリプト、プレハブをできる限りフォルダごと管理するようにしてください。
プロジェクトウィンドウのGameをドラッグ&ドロップでScenesフォルダに移動してください。
移動先のScenesフォルダのSampleSceneを削除しておきましょう。
メインカメラの調整
オブジェクトをこれから作っていきますが、Gameシーンでの見た目と同じ形で作成していくと効率が良いので、下のGIFと同じ様にSceneビューをメインカメラの方向と同じ様にします。
Main CameraのPositionは0,0,-10
壁の作成
初めに壁を作ります。まず整理しやすいようにHierarchy > Create Emptyをクリックします。空のGameObjectができたら、名前をWallsに変更しておきます。
このWallsの中に壁のオブジェクトを作っていきます。下の表のように4つのオブジェクト(HierarchyビューでCreate > 3D Object > Cube)を作成してください。
オブジェクト名 | Position | Scale | ||||
X | Y | Z | X | Y | Z | |
Wall1(右壁) | 26 | 0 | 0 | 1 | 100 | 1 |
Wall2(左壁) | -26 | 0 | 0 | 1 | 100 | 1 |
Wall3(上壁) | 0 | 50 | 0 | 53 | 1 | 1 |
Wall4(下壁) | 0 | -50 | 0 | 53 | 1 | 1 |
以上で今回使用する壁が完成しました。
ボール(Ball)の作成
次にボールを作成します。HierarchyビューでCreate > 3D Object > Sphereを選択し、名前を「Ball」に変えます。
このままだとボールが思ったより小さいので、大きくします。
Position:(0,0,0)
Scale:(2.2.2)
ボールに物理演算を加える
このままだとただの何もできない球となってしまうので、物理演算を付けて跳ね返ったりするようにします。
HierarchyビューでBallを選択し、InspectorビューでAdd Component > Rigidbodyを追加します。
これで物理演算は入れられたのですが、1点注意点として、Rigidbodyはデフォルトで「Use Gravity」にチェックが入っています。今回のゲームではGravityは使用しないので、Use Gravityのチェックを外してください。
ボールが動くように初速を与える
さて次はボールに初速を与えて動くようにします。
初速を与えるためにC#スクリプトを作成します。
整理のためにスクリプトをまとめるフォルダを作ります。
ProjectビューでCreate > Folderを選び、作成されたフォルダを「Scripts」という名前に変更します。
今後はスクリプトを全てこのフォルダに保存していきます。
では、ボールに初速を与えるスクリプトを作ります。
Scriptsを右クリックして、開かれたメニューからC# Scriptを選択します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Ball : MonoBehaviour { //初速を入力値として準備します。 public float speed = 100; private void Start() { // rigidbodyを取得 Rigidbody rb = this.GetComponent<Rigidbody>(); // 力を設定 Vector3 force = new Vector3(10.0f,10.0f,0.0f)*speed; // 力を加える rb.AddForce(force); } } |
壁にぶつかった後に跳ね返ってほしいのに跳ね返っていませんね。
ブロック崩しであればボールは適切に跳ね返らなければなりません。
正しく反射するように設定する
そこで、跳ね返り係数を調整できるAssetである、Physic Materialを作成します。
ProjectビューでCreate > Physic Materialを選択します。
作成したPhysic Materialを「Material Physic」と名前を変更し、Inspectorビューで下の画像のように変更します。
Physic Material(物理特性マテリアル)についてもう少し知りたい方は、こちらの記事で詳細に説明しているので、参考にしてみてください。
設定が終わったらBallとWall1,2,3,4にアタッチします。
例えばBallの場合、Projectビューの「Ball Physic」をHierarchyビューの「Ball」へドラッグアンドドロップします。
すると下の画像のように、InspectorビューのSphere ColliderのMaterialに挿入されているのが確認できます。
これで跳ね返りを実現できました。(ボールを見やすいように色付けました。)
パドル(Bar)の作成
次にパドルを作成します。
HierarchyビューでCreate > Cubeで作成します。
名前は「Bar」に変更して、Position,Rotation,Scaleを以下のようにします。
次に動かせるようにBarのスクリプトを作成します。
ProjectビューでCreate > C# Scriptを選択し、名前を「Bar」にします。
スクリプトは以下を使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Bar : MonoBehaviour { void Update() { //左キーを入力すると左にBarが動く if (Input.GetKey(KeyCode.LeftArrow)) { this.transform.Translate(-0.5f, 0f, 0f); } //右キーを入力すると右にBarが動く if (Input.GetKey(KeyCode.RightArrow)) { this.transform.Translate(0.5f, 0f, 0f); } } } |
このスクリプトをBarにアタッチすると、自分でパドルを動かせるようになります。
更に先ほど作成した「Material Physic」をBarにアタッチしてあげます。(衝突でのエネルギー減少を失くすため)
すると以下のようによりブロック崩しっぽくなります。
このままでは壁からパドルが出てしまいますね。
壁から出ないようにパドルの移動範囲に制限を加えましょう。
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Bar : MonoBehaviour { void Update() { //Barの座標を取ります。 Transform BarTrans = GameObject.Find("Bar").transform; Vector3 pos = BarTrans.position; if (Input.GetKey(KeyCode.RightArrow)) { //Barの座標が20以下(壁より内側)である場合には移動を実施します。 if (pos.x < 20) { this.transform.Translate(0.5f, 0f, 0f); } } if (Input.GetKey(KeyCode.LeftArrow)) { //Barの座標が-20以上(壁より内側)である場合には移動を実施します。 if (pos.x > -20) { this.transform.Translate(-0.5f, 0f, 0f); } } } } |
スクリプトによってパドルの座標を制限することで、壁内でしか動かないようにしています。
これで壁からはみ出さなくなりました。
ブロック(Block)の作成
さて、次にブロックを作成します。沢山のブロックを大量に作成する場合にはPrefab(プレハブ)を使用する方が効率的なので、今回はPrefabを使用します。
まず、HierarchyビューでCreate > 3D Object > Cubeを選び、名前を「Block」とします。
Position、Rotation、Scaleについて下の画像のように設定してください。
次に、ボールがぶつかった時に消滅するようにします。
スクリプトで実装するので、いつも通り、ProjectビューでCreate > C# Scriptを選択し、名前を「Block」にします。
スクリプトは以下を使用します。OnCollisionEnterは衝突を判定する関数であり、衝突が発生したらDestroy関数を使ってBlockを消滅させます。
1 2 3 4 5 6 7 8 9 10 11 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Block : MonoBehaviour { private void OnCollisionEnter(Collision collision) { Destroy(gameObject); } } |
このスクリプトをHierarchyビューの「Block」へドラッグアンドドロップでアタッチします。
以下のようになれば問題ありません。
更に先ほど作成した「Material Physic」をBarにアタッチしてあげます。(衝突でのエネルギー減少を失くすため)
これでBlockの設定が完了したので、次は複製します。
Prefabについて詳細に説明している記事があるので、興味ある方は良かったらご一読ください。
Prefab化およびオブジェクトの複製は以下の手順で実施します。
- HierarchyビューのBlockをProjectビューにドラッグアンドドロップをして、Prefab化する。
- Prefab化されたProjectビューのBlockをHierarchyビューにドラッグアンドドロップする。すると、Block(1)が作成される。
- 2を繰り返し、Block(14)まで作成する。
- 各オブジェクトを以下の画像の座標(Position)に変更する。
以上で、Blockの準備が完了しました。
Blockの色は好みで変更してください。色の設定方法やグラデーションの付け方など、色々と解説している記事があるので、是非ご参考ください。
さて、これで見た目はほぼブロック崩しになりました。
しかし、このままだとゲームクリアとゲームオーバーの判定が出来ていません。
ゲームクリアの判定
Hierarchyビューの整理も兼ねて、まず、Block~Block(14)を1つの空のゲームオブジェクトの配下にまとめます。
HierarchyビューのCreate > Create Emptyを選択し、作成されたGameObjectの名前を「Blocks」にします。
そして、Block(14)までを選択し、Blocksにドラッグアンドドロップします。
次に、ゲームクリアを表す「GAME CLEAR!」という文字を用意します。
HierarchyビューのCreate > UI > Textを選択し、名前を「ClearUI」に変更します。
続いて、ClearUIオブジェクトの内容を設定します。
InspectorビューでRectTransformの値を以下の画像と同じ値に設定します。
これで、クリアの文字の準備はできました。次にクリアの条件を設定します。
今回のクリアの条件は、全てのBlockが消滅することなので、Blocksの中のオブジェクトが無くなったらクリアとします。
さて、この条件をスクリプトで作成します。
まず、ProjectビューでCreate > C# Scriptを選択し、名前を「GameController」とします。
スクリプトは以下を使用します。このスクリプトは、「Block」というタグが付いているオブジェクトが0になった時に、ClearUIがアクティブになるというものです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class GameController : MonoBehaviour { public GameObject ClearUI; public void Update() { int count = GameObject.FindGameObjectsWithTag("Block").Length; if (count == 0) { // オブジェクトをアクティブにする ClearUI.SetActive(true); } } } |
次にHierarchyビューで「GameController」というオブジェクトを作成します。
HierarchyビューでCreate > Create Emptyを選択し、名前を「GameController」とします。
そして、作成したGameControllerオブジェクトにGameControllerスクリプトをアタッチします。
更にInspectorビューでClearUIをScriptのClearUIに設定します(参照できるようにします。)
今のままだとスタート時からClearUIが表示されている状態になっているので、非表示に変更します。(Inspectorビューから変更できます)
最後に、ClearUIがアクティブになる条件である、「Block」のタグを各Blockに設定します。
ここでPrefabを使用していることのメリットが生かされます。
以下の手順で行います。
- ProjectビューでBlockプレハブをダブルクリックします。
- するとプレハブの設定がInspectorビューに表示されるので、TagのUntaggedをクリックします。
- Blockというタグはデフォルトでは存在しないので、自分で作成する必要があります。表示されたメニューの一番下にある「Add Tag…」をクリックします。
- すると以下の画面が開かれるので、+をクリックします。
- New Tag Nameを「Block」とし、Saveをクリックします。
- Hierarchyビューに表示されているBlockのプレハブをクリックして、InspectorビューをBlockに戻します。
- 先程作成したBlockというタグを設定します。TagのUntaggedをクリックし、Blockを選択します。
- 最後に設定を保存するために、Hierarchyビューの<をクリックして、開かれたダイアログのSaveを選んで保存します。
以上で、Tagの設定も完了し、ゲームクリアの設定が完了しました。
ゲームオーバーの判定
ゲームクリアが設定できたので、ゲームオーバーの設定も行います。
今回ゲームオーバーの条件は、下の壁に接触してしまうこととします。
下の壁に接触した場合、Playerの球が消滅し、GAME OVERと表示されるようにします。
まず、下の壁に接触した時にPlayerの球が消滅するようにします。
いつも通りProjectビューで「DestroyBall」というC# Scriptを作成します。
スクリプトは以下を使います。
1 2 3 4 5 6 7 8 9 10 11 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class DestroyBall : MonoBehaviour { private void OnCollisionEnter(Collision collision) { Destroy(collision.gameObject); } } |
このスクリプトを下の壁(Wall4)にアタッチします。
すると以下のように確かにボールが消えるようになりました。
次に、ゲームクリアと同じ様にUIで「GAME OVER」を作成します。
- Create > UI > Textを選択します。
- 名前を「GameOverUI」とし、諸々設定します。
- GameControllerスクリプトの内容を以下に変更します。仕組みはクリアと全く同じです。
1234567891011121314151617181920212223242526using System.Collections;using System.Collections.Generic;using UnityEngine;public class GameController : MonoBehaviour{public GameObject ClearUI;public GameObject GameOverUI;public void Update(){int count = GameObject.FindGameObjectsWithTag("Block").Length;int count1 = GameObject.FindGameObjectsWithTag("Player").Length;if (count == 0){// ClearUIをアクティブにするClearUI.SetActive(true);}if (count1 == 0){//GameOverUIをアクティブにするGameOverUI.SetActive(true);}}} - HierarchyビューのGameControllerオブジェクトをクリックし、InspectorビューでGameOverUIの部分に「GameOverUI」をアタッチします。
- HierarchyビューのGameOverUIをクリックし、InspectorビューでTagを「Player」とし、チェックを外します。(非アクティブ化)
- 最後に、Ballが消えた時にGameOverとなってほしいので、Ballにタグを設定します。InspectorビューでBallのTagを「Player」に変更します。
以上でGameOverの設定も完了しました。
ゲームクリアとゲームオーバーが同時に発生しないように設定
実はこのままでは、ゲームクリア後もボールは残ったままで、下の壁についた瞬間にゲームオーバーの文字も表示されてしまうという問題が残っています。
そこで、GameControllerスクリプトを変更することで上記現象が発生しないようにします。
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 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class GameController : MonoBehaviour { public GameObject ClearUI; public GameObject GameOverUI; public void Update() { int count = GameObject.FindGameObjectsWithTag("Block").Length; int count1 = GameObject.FindGameObjectsWithTag("Player").Length; if (count == 0) { // ClearUIをアクティブにする ClearUI.SetActive(true); // クリア時にBallを消滅する GameObject obj = GameObject.Find("Ball"); Destroy(obj); } // Ballが無くなり、かつBlockが残っている時にゲームオーバーとなる条件 if (count1 == 0 && count != 0) { //GameOverUIをアクティブにする GameOverUI.SetActive(true); } } } |
各オブジェクトに色を付けて完成
最後は自分の好みで各オブジェクトの色を変更して、完成です!
まとめ
いかがでしたでしょうか。
ゲーム作りの登竜門である、ブロック崩しゲームをご紹介してきました。
大分長くなってしまいましたが、これをきっかけにUnityをもっと開発できるようになれば幸いです。
また、このブロック崩しゲームはまだまだ改善の余地があるので、改善版も後日アップロードしようと思います。
以下のような改善余地(課題)があるので、もし余裕がある方は実装してみてはいかがでしょうか。
・ボールのスタートの角度をランダムにする
・バーにあたる場所によって挙動を変える
・ブロック毎に耐久力を付ける
・残機をつける
・スコアをつける
・アイテムを設定する
・BGMやSEをつける
・ブロックを崩すときのエフェクトをつける
この記事はいかがでしたか?
もし「参考になった」「面白かった」という場合は、応援シェアお願いします!