Skip to main content

ブロック崩しゲームの作り方

プロジェクト設定

プロジェクト作成

まず、新規プロジェクトを作成しましょう。2Dゲームであるため「Universal 2D」を選んでください。プロジェクト名は「breakout」にしましょう。

image.png

素材を追加

ゲームに必要な素材を「Project」に追加しましょう。今回必要なのは

  • 画像、絵
    • プレーヤーの「パドル」
    • ボール
    • 各種のブロック(レンガ)
    • 背景
    • UIに使う「ゲームオーバー」とボタン
  • サウンド
    • BGM
    • 効果音
      • ボールとパドルの衝突
      • ボールと壁の衝突
      • ボールが失うときの音
      • ブロック崩す時の音

「Sprites」と「Sound」フォルダを作成し、適切にファイルをコピーしてください。

image.png

シーンを構築

スプライトを追加

「SampleScene」の名前はカッコ悪いので、「Game」に書き換えましょう。シーンの名前を変更するには

  • 「プロジェクト」の中で「Scenes / SampleScene」を選択
  • キーボードで「F2」を押す
  • 「Game」の名前にする

次、背景とプレーヤーのパドルを追加しましょう。プロジェクトから「Sprites / Background」と「Sprites / Player」をドラッグドロップでシーンに追加。

image.png

ヒエラルキーに2つの新しいゲームオブジェクトが現れたことを確認してください!

スプライトの表示順番

場合により、背景のみ表示され、プレーヤーのパドルが表示されないときもある。なぜなら、背景はパドルの手前に表示されているので、パドルが後ろに隠れているため。

直し方は2つある:

「SpriteRenderer」の「Order In Layer」を調整

「Order In Layer」を調整することにより、スプライトの表示順番を変えることができる。数値が小さければ小さいほど、後ろから先に表示される。つまり、「背景」は小さくし、「前景」を大きい数値にすれば良いでしょう。

Background と Player は両表とも「0」になっているため、ランダムに順番が決め、パドルがたまに手前に現れ、時々は後ろに隠れてしまう。これを防ぐには、Playerの「Order In Layer」は 0 よりも大きい数値にしましょう。例えば、「10」にすると:

image.png

パドルが必ず手前に出る。

「ゲームオブジェクト」の Z軸位置を調整

2Dゲームの場合は「X軸」(左右)と「Y軸」(上下)しかないと思われるが、実は「Z軸」もある。Z軸で、各オブジェクトの表示順番も調整ができる。カメラに近いものを手前に表示されるので、パドルの Z位置は少し小さめすれば良いでしょう

※:Z軸は大きいほど奥になること忘れずに~

image.png

実は、3D空間で確認してみると:

image.png

パドルが背景の手前にあることを確認ができる!

表示範囲を調整

とりあえず、画面サイズがFullHDをターゲットにしましょう。ゲームビューで「FullHD (1920x1080)」のサイズを選んでください

image.png

これで、背景は微妙に入らないことがわかる。なぜなら、FullHDだと、カメラの映る範囲は背景よりも小さいからです。

image.png

これを直すには、カメラの「範囲」を少し広くすれば良いでしょう。ヒエラルキーで Main Camera を選択し、「Size」パラメタを調整してみてください。背景がぴったり入るように適切な値をしてみてください。

最後、プレーヤーのパドルを画面の下の方に適切に配置してください。

image.png

物理:コライダーとリジッドボディ

パドルが物理を使って、動かすし、壁とボールの衝突するべきで、コライダーとリジッドを設置しないければならない。

背景

プレーヤーとボールがプレイエリアからはみ出さないように、各壁(右、左、上)にコライダーを付けましょう。

Backgroundの下に子供オブジェクトとして1つのオブジェクト「Wall Left」を追加し、「Box Collider 2D」のコンポーネントを追加してください。また、コライダーのサイズを調整し、左側の壁に合わせてみてください:

image.png

同じ手順で、右側(Wall Right)と上(Wall Top)のコライダーを作ってください。

image.png

パドル

プレーヤーのパドルの衝突には、もちろん、コライダーが必要で、物理的に動かす予定で、リジッドボディも必要。「Player」に「BoxCollider2D」と「Rigidbody2D」を追加してください。

 

このままゲーム開始すると、プレーヤーのパドルが落下します。重力がかかるし、回転、移動は無制限なので、制約(Constraint)を付けなければならない。

 

まず、重力が影響しないように、「Gravity Scale」は「0」にしましょう。そして「Constraints」は回転できないように「Freeze Rotation」をチェックし、X軸のみで移動するため、Y軸の移動も固定してください(Freeze Position Y)

image.png

パドル(Player)の移動

パドルが左右に移動できるようにしましょう。このスクリプトを使って:

    左キーと右キーがInspectorで設定できるようにしたい。 速度もInspectorで調整できるようにしたい。 右か左キーを押したら、設定した速度をリジッドボディに与える(Rigidbody2D.linearVelocity)

    スクリプトの変数

    using UnityEngine;
    
    // パドルを移動するスクリプト
    public class PlayerMove : MonoBehaviour
    {
        // 速度をInspectorで設定
        [SerializeField]
        private float speed;
    
        // 左へ移動するキーをInspectorで設定
        [SerializeField]
        private KeyCode leftKey;
    
        // 右へ移動するキーをInspectorで設定
        [SerializeField]
        private KeyCode rightKey;
    
        // 物理的動かすためのリジッドボディ
        private Rigidbody2D _rigidbody;
    }

    これで新しい PlayerMove のスクリプトを作成し、必要なデータ(変数)を準備ができた。Inspectorで編集するべきの変数に [SerializeField] を頭につけ、アクセス修飾子は private であっても、Unityで見えるようになる。

    リジッドボディは Start() で取得するため、[SerializeField] は不要で、プログラムの中で代入する予定。

    変数の先頭につけるアンダーバーについて
    変数の先頭につけるアンダーバーについて

    固いルールではないが、開発者の「いいマナー」としてのルールであり、変数名を見るだけで、アクセス権限がわかるためのものである。

      Unityで編集するメンバー変数小文字で始まる。
      // 速度
      [SerializeField]
      private float speed;
      
      // 最大体力
      [SerializeField]
      private int maxHP;
      
      // ステージの名前
      [SerializeField]
      private string stageName;
        クラス内部に使う private メンバー変数アンダーバーで始まる。
        // 現在の体力
        private float _nowHP;
        
        // リジッドボディコンポーネントの参照
        private Rigidbody2D _rigidBody;
        
        // アイテムの位置
        private Vector3 _itemPosition;
          公開された public メンバー変数大文字で始まる。
          // コインの数
          public int Coins;
          
          // 最大体力(読み込み専用)
          public int MaxHP {
            get { return _maxHP; }
          }
          
          // 現在の体力
          public string NowHP
          {
            get { return _nowHP; }
            set { _nowHP = Mathf.Clamp(value, 0, _maxHP); }
          }
            メソッドはいつも大文字で始まる。
            // 攻撃する
            public void Attack()
            {
            }
            
            // ゲームオーバーになったかを確認
            private void IsGameOver()
            {
            }
            
            // フレーム毎の処理 
            private void Update()
            {
            }
              メソッド内部で使うローカル変数はいつも小文字で始まる。


               

               

              初期化 - Start()