ひとりでのアプリ開発 - fineの備忘録 -

ひとりでアプリ開発をするなかで起こったことや学んだことを書き溜めていきます

Unity入門 - ブロック崩しを作ってみよう② -

初めに


 ブロック崩しを作ってみようの後半戦です。入力を受け取り、バーを操作したり、ブロックが壊れるようにしたりします。
 この記事は、以前の記事の続きになります。まずは、そちらをご覧ください。
fineworks-fine.hatenablog.com

バーを動かせるようにする

 キー入力を取得し、バーを動かせるようにします。キー入力の取得の仕方は、次の記事にまとめております。
fineworks-fine.hatenablog.com

 バーに次のスクリプトをアタッチしましょう。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BarScript : MonoBehaviour
{
    public float speed = 0.1f;  //インスペクターから速度を調整できるようにしている

    void Update()
    {
        if (Input.GetAxis("Horizontal") > 0)  //キーボードならば→を押されたら
        {
          if(this.transform.position.x <=  2.5f)  //x座標が2.5より大きくならないようにする
          {
            this.transform.position += new Vector3(speed, 0.0f, 0.0f);
          }
        }
        else if(Input.GetAxis("Horizontal") < 0)  //キーボードならば←を押されたら
        {
          if(this.transform.position.x >=  -2.5f)  //x座標が-2.5未満にならないように
          {
            this.transform.position += new Vector3(- speed, 0.0f, 0.0f);
          }
        }
    }
}

 これで、バーが操作できるようになりました。speedをpublicにしているのは、インスペクターからspeedを変更できるようにするためです。

 補足になりますが、バーにRigidbodyをアタッチしないようにしましょう。ボールからバーに力が加わり、次の動画のようになります。

ブロックを作る

 ブロックを生成し、ボールが当たったら壊れるようにしましょう。当たり判定の取得の仕方はこちらの記事をご覧ください。

fineworks-fine.hatenablog.com

  • Cubeを生成する(名前はBlockに変えておく)
  • 次のスクリプトをBlockにアタッチする
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BlockScript : MonoBehaviour
{
    //当たり判定の取得, 何かに当たったら呼ばれる
    void OnCollisionEnter(Collision Collision) 
    {
      //接触したオブジェクトの名前が"Sphere"だったら
      if(Collision.gameObject.name == "Sphere")  
      {
        Destroy(this.gameObject);  //このオブジェクトを削除する
      }
    }
}
  • BlockのインスペクターからScaleを (1, 1, 0.5) に変更
  • Blockを16個複製(Win:Ctrl + D, Mac:⌘ + D)
  • BlockのインスペクターからPositionを次のように変更

名前 Position
Block (-3.5, -2, 5)
Block (1) (-2.5, -2, 5)
Block (2) (-1.5, -2, 5)
Block (3) (-0.5, -2, 5)
Block (4) (0.5, -2, 5)
Block (5) (1.5, -2, 5)
Block (6) (2.5, -2, 5)
Block (7) (3.5, -2, 5)
Block (8) (-3.5, -2, 5.5)
Block (9) (-2.5, -2, 5.5)
Block (10) (-1.5, -2, 5.5)
Block (11) (-0.5, -2, 5.5)
Block (12) (0.5, -2, 5.5)
Block (13) (1.5, -2, 5.5)
Block (14) (2.5, -2, 5.5)
Block (15) (3.5, -2, 5.5)

 これで、ブロックは完成しました. Blockがヒエラルキーを圧迫して見にくいのと、今後の都合のために、Blockはまとめておきましょう。

  • 空のゲームオブジェクトを作成(ヒエラルキーで右クリックし、Create Emptyをクリック)し、名前を "Blocks" に変更
  • すべてのBlockをBlocksの子オブジェクトにする(Blockを選択し、Blocksにドロップ)

 下の画像のような状態になっていれば、OKです。実行してみると、ブロックにボールが当たった時に、ブロックが壊れるようになっているはずです。

※画像はBlockにMaterialをアタッチし、色を変更しております。

ブロックの作り方の補足

 今回は、Unityを初めて触る人にでも作れるようにプレハブ(Prehab)を使わない方法を採用しております。本当は、Prehabを作り、スクリプトから生成、Positionを変更してしまったほうが作業自体は楽になります。

ゲームスタート、ゲームクリア、ゲームオーバーを作る

ゲームスタート

 今回は、ボタンを押したらボールが発射されるようにすればよいでしょう。ボタンの使い方はこちらの記事をご覧ください。

fineworks-fine.hatenablog.com

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SphereScript : MonoBehaviour
{
    //public GameObject Sphere;
    public GameObject StartButton;

    // Start is called before the first frame update
    void Start()
    {
      //StartにあったスクリプトをすべてonClickButton内に移す
      // Rigidbody rb = this.GetComponent<Rigidbody>();
      // Vector3 force = new Vector3(5f, 0.0f, 6f);
      // rb.AddForce(force, ForceMode.VelocityChange);
    }
    
    public void onClickButton()
    {
      Rigidbody rb = this.GetComponent<Rigidbody>();
      Vector3 force = new Vector3(5f, 0.0f, 6f);
      rb.AddForce(force, ForceMode.VelocityChange);

      //押されたら最後にボタンを削除
      Destroy(StartButton.gameObject);
    }
}
  • Buttonを生成(ヒエラルキーで右クリック→UI→Button)し、名前を "StartButton"に変更
  • StartButtonの子オブジェクトであるtextを "スタート"に変更
  • SphereにアタッチされているスクリプトのStartButtonにStartButtonをドラッグ


  • StartButtonにSphereをアタッチ、onClickButtonを選択する


 実行すると、ボタンを押したらボールが発射され、スタートするようになりました。

ゲームクリア

 ブロックをすべて壊せばクリアと表示されるようにします。

  • 空のゲームオブジェクトを作成(ヒエラルキーで右クリックし、Create Emptyをクリック)し、名前を "GameManager" に変更
  • 次のスクリプトをGameManagerにアタッチする
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;  \\Textを使うので, UIを追加

public class ClearScript : MonoBehaviour
{
    public GameObject Blocks;  //Blockの親オブジェクトを取得
    public GameObject Sphere;  //Sphereを取得

    public GameObject ClearText;  //Textを取得
    Text _cleartext;

    void Start()
    {
      _cleartext = ClearText.GetComponent<Text>();
      _cleartext.text = "";
      ClearText.SetActive(false);  //Textを非表示にしておく
    }

    // Update is called once per frame
    void Update()
    {
        if(Blocks.transform.childCount == 0)  \\Blocksの子オブジェクトの個数が0になったら
        {
            ClearText.SetActive(true);  //Textを表示
            _cleartext.text = "Clear";

            Destroy(Sphere);  //Sphereを削除
        }
    }
}
  • Canvasの子オブジェクトにTextを生成し、名前をClearTextにしておく
  • GameManagerにBlocks、Sphere、ClearTextをアタッチする


 これで、クリアの判定ができました。

ゲームオーバー

 下のCubeにボールが接触したら、ゲームオーバーと表示されるようにしましょう。

  • 先ほどのClearScriptに下記のように追記する
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;  \\Textを使うので, UIを追加

public class ClearScript : MonoBehaviour
{
    //Start, Updateの下に次を追加
    void OnCollisionEnter(Collision Collision)
    {
      //当たったオブジェクトの名前がSphereだったら
      if(Collision.gameObject.name == "Sphere")  
      {
        ClearText.SetActive(true);
        _cleartext.text = "GameOver";

        Destroy(Sphere);
      }
    }
}
  • Cube(1)にClearScriptをアタッチし、スクリプトにBlocks、Sphere、ClearTextをアタッチする


 これでゲームオーバーの処理もできました。

完成

 お疲れさまでした。ひとまずこれで完成になります。Unityの基本的な操作に慣れることができたのではないかと思います。

さらに発展させるには

 タイトルシーンをつけたり、クリアしたら次のステージに進めるようにしたりするなど、改善しようとすれば、際限がありません。また、実際にアプリとしてビルドするならば、PCやAndroidなどプラットフォームを選んでおき、画面サイズ等合わせて作っていくことになるでしょう。

 また、ゲーム性がまだないため、自分でプレイしてみても、面白くないかもしれません。ここにゲーム性を足してリリースしてみるのも選択肢の一つではないかと思います。

最後に

 今までの記事で学んだことを復習しながら作れるように記事を書きました。当たり判定の取り方やオブジェクトの動かし方、GetComponentなどUnityを使ううえで必須となるものばかり使っております。最終的に何も見なくてもブロック崩しを作れるまで慣れると基本操作で困ることが少なくなると思います。
 今後は、引き続きプレハブの使い方やAnimationの使い方などUnityの解説の記事以外にもドット絵のソフト紹介などゲーム作りに役立ちそうな記事を上げていくつもりです。ぜひ、ご覧ください。