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

スクリプト専用のフォルダを作成

Project の中に「Scripts」の新しいフォルダーを作成し、新しスクリプト「PlayerMove」を作成してください。

パドル(Player)の移動

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

  • 左キーと右キーがInspectorで設定できるようにしたい。
  • 速度もInspectorで調整できるようにしたい。
  • 右か左キーを押したら、設定した速度をリジッドボディに与える(Rigidbody2D.linearVelocity)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); }
}
  • 上記以外の変数はいつも小文字で始まる。
// 引数の変数は:小文字
private int Sum (int a, int b)
{
  // 内部で使う変数も小文字
  int c = a + b;
  return c;
}
    メソッドはいつも大文字で始まる。
    // 攻撃する
    public void Attack()
    {
    }
    
    // ゲームオーバーになったかを確認
    private void IsGameOver()
    {
    }
    
    // フレーム毎の処理 
    private void Update()
    {
    }
      メソッド内部で使うローカル変数はいつも小文字で始まる。

      初期化 - Start()

      パドルの初期化はほとんどなく、あくまで、リジッドボディの参照を取得しておきたい。このスクリプトはパドルにアタッチするべきなので、GetComponent で簡単に取れる。PlayerMove クラスに以下のメソッドを追加してください

      private void Start()
      {
          _rigidbody = GetComponent<Rigidbody2D>();
      }

      フレームごとの更新 - Update()

      フレームごとに、右か左のキーが押されたかどうかを確認し、押されていたら、その向きに移動する。一方、キーが押されていなかったら、パドルを止める(速度をゼロにする)

      PlayerMove クラスに以下のメソッドを追加してください:

      private void Update()
      {
          // 前提として速度はゼロにする。
          var velocity = Vector2.zero;
      
          // ただし、左キーが押されたら
          if (Input.GetKey(leftKey))
          {
              // x軸の速度を左の方(マイナス軸)にする
              velocity.x = -speed;
          }
      
          // 右のキーが押されたら
          if (Input.GetKey(rightKey))
          {
              // x軸の速度を右の方(プラス軸)にする
              velocity.x = speed;
          }
      
          // 最後に、計算した速度をリジッドボディに与える
          _rigidbody.linearVelocity = velocity;
      }

      試してみましょう!

      スプライトを Player にアタッチし、右キーと左キーを設定の上、速度を設定してください。そして、ゲーム開始して、動くかどうかを確認してください。

      image.png


       

       

      初期化 - Start()