【Unity】2Dシューティングゲームの作り方④:弾の発射処理

Unity

こんにちは、ともくんのゲーム作り部屋にようこそ!

このページでは、Unityを使った2Dシューティングゲームの作り方4回目として、プレイヤーの弾の発射処理について紹介しています。

前回、プレイヤーをキー操作で移動できるようになりました。

今度はプレイヤーから弾を発射させるために、キー操作を使って弾を表示させるという処理を作っていきます。

弾を表示させるためには、いくつか方法がありますが、よく使うのがPrefab化Instantiate関数です。

そこで、プレイヤーの弾のオブジェクトを配置して、Prefab化、また発射できるまでをまとめていきます。

この記事を書いた人

ゲーム作りを学び始めた一児のパパです。
このブログは、子供から「ゲームを作ってみたい!」と言われ、非プログラマーでゲーム作りをしたことない僕が、ゲーム作りの本を読んで独学でゲーム開発を学んでいるブログです。
同じように初めてゲーム作りをしている方と一緒に学んでいけるようなブログに出来たらいいなと思っています。
また、「このコードはおかしい」とか「もっと良い書き方があるよ!」などあれば、どんどん指摘して頂けると助かります。

弾を移動させる

まずは、弾をゲーム内に配置して移動させるスクリプトを作っていきます。

アセットフォルダから、プレイヤーの弾をゲーム内のどこでも良いので、配置させておきます。

今回は、プレイヤーの弾なので「playerBullet」という名前にしています。

そして、この弾を移動させるためのスクリプトを新たに作成します。

スクリプトの作成は、プレイヤーのスクリプトの際と同じく、プロジェクトウィンドウの「+」ボタンから「MonoBehaviourScript」を選択します。

スクリプト名は、プレイヤーの弾を移動させるスクリプトとして、「PlayerBulletMove」としています。

このスクリプトを先ほど配置したプレイヤーの弾のオブジェクトにアタッチさせて、以下のスクリプトを書いていきます。

using UnityEngine;

public class PlayerBulletMove : MonoBehaviour
{
    float playerBulletSpeed = 0.2f;   // 弾のスピードを決める変数

    void Update()
    {
        transform.Translate(0, playerBulletSpeed, 0); // Y座標をプラスに動く
        if (transform.position.y > 5)   // Y座標が5より大きい場合
        {
            Destroy(gameObject);    // オブジェクトを破壊する
        }
    }
}

5行目で、弾の速度を決める変数を宣言しています。

また、Updateメソッド内の9行目でプレイヤーを移動させたときと同じく、transform.Translateを使って、弾をY軸にまっすぐ移動させる処理を書いています。

そのままだと、画面外にいってもずっと残り続けることになるので、10~13行目でif文を使って画面外の座標に弾が移動したら、Destroy関数弾を消す処理を書いています。

Destroy関数は、後ろに引数でオブジェクトを指定してあげることで、そのオブジェクトを破壊する、つまり削除するという処理を行います。

今回は、このスクリプトがアタッチしているオブジェクトを破壊したいので、引数に「gameObject」と設定しています。

これで実際に、ゲームを実行してみると、

のように、弾がまっすぐに移動できていることが分かります。

なお、変数スクリプトif文などは前回のプレイヤーの移動処理の際にも紹介しましたが、以下のページにまとめていますので参考にしてみてください。

弾をPrefab化する

次に、先ほど作成した弾をPrefab(プレハブ)化していきます。

このPrefab化とは、そのオブジェクトと全く同じオブジェクトを複製することができるようになるUnityの機能です。

弾は、何度も撃つことになり、毎回オブジェクトを複製することになるので、Prefabを使って作成していきます。

Prefab化の作り方は非常に簡単で、ヒエラルキーウィンドウに配置してある弾のオブジェクトを、アセットフォルダに向かってドラッグ&ドロップするだけです。

これでPrefab化されたオブジェクトが、アセットフォルダ内に作成されます。

今回は、このPrefab化したファイルを「PlayerBullet」という名前にして、「Prefabs」というフォルダの中に保存しています。

なお、Prefab化ができたら、ゲームビューに配置した弾のオブジェクトは一旦削除しておきます。

これで弾のPrefab化の処理が完了しました。

空オブジェクトを作成する

次に、先ほどPrefab化した弾のオブジェクトを、表示させるために空のオブジェクトを作成します。

弾を表示させるためにスクリプトが必要になりますが、スクリプトを使うためにはオブジェクトにアタッチしないと処理が出来ないので、空のオブジェクトを作成してそこにアタッチすることになります。

空オブジェクトの作成は、ヒエラルキーウィンドウの+ボタンから「Create Empty」で作成します。

この空オブジェクトを使って弾を撃つ場所を決めていくことになるので、「playerBulletPoint」という名前にしています。

そして、この空オブジェクトをプレイヤー(player)の子オブジェクトにしておきます。

なぜ子オブジェクトにするかというと、オブジェクト同士を階層にして親子関係にしておくことで、プレイヤーを動かしても、常に弾の発射位置を同じ場所にすることができるからです。

ヒエラルキーウィンドウで空オブジェクトをドラッグして、プレイヤーのオブジェクトの上で離せば、子オブジェクトにすることができます。

親子関係が作れたら、この空オブジェクトの座標位置をプレイヤーの弾を発射させたい位置に移動させておきます。

これで、プレイヤーが移動しても常に発射位置を固定する空オブジェクトを作ることができました。

弾を発射するスクリプト

ここからは、弾を実際に表示して発射するスクリプトを作っていきます。

プロジェクトウィンドウから、「MonoBehaviourScript」を選択して新しいスクリプトを作成します。

このスクリプト名は、プレイヤーが弾を発射する処理を入れていくことになるので、「PlayerShoot」という名前にしています。

そして、このスクリプトを先ほど作成した空オブジェクトのplayerBulletPointにアタッチしておきます。

using UnityEngine;

public class PlayerShoot : MonoBehaviour
{
    public GameObject playerBullet; // public修飾子を付けてGameObject型の変数を宣言する

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Return))   // Enterキーを押した場合
        {
            Instantiate(playerBullet, this.transform.position, Quaternion.identity);  // 弾を表示させて座標を移動させる処理
        }
    }
}

5行目でGameObject型の変数playerBulletを宣言しています。

この変数は、Prefab化した弾のオブジェクトを入れるための変数となりますが、後ほどインスペクターウィンドウで代入を行うために、publicというアクセス修飾子を付けて設定しています。

このアクセス修飾子とは、その変数やメソッドなどがどこからアクセスできるかを決めているもので、publicは全公開でどこからでもアクセスできることを表しています。

9~12行目で、Input.GetKeyDownメソッドEnterキーを押した際にそのオブジェクトを複製するInstantiate関数を書いています。

このInstantiate関数とは、引数に設定したオブジェクトを複製する処理を行うメソッドになっています。

そのため、最初に宣言した変数playerBulletを引数として設定しています。

Instantiate(playerBullet)

ただし、そのままだとPrefab化した際のオブジェクトの座標に、弾が複製されて表示されることになります。

そこで、Instantiate関数の第二引数に表示させたい座標として「this.transform.position」と書くことで、このスクリプトをアタッチしているplayerBulletPointの座標を指定することができます。

なお、第三引数にはオブジェクトの回転量を設定することができますが、今回は特に変更がいらないので、複製するオブジェクトと同じ回転量を表している「Quaternion.identity」を書いています。

Instantiate(生成したいオブジェクト, 生成する座標, オブジェクトの回転量);

スクリプトを作成したら、Unityに戻り空オブジェクトのplayerBulletPointを選択して、インスペクターウィンドウのPlayerShootスクリプトから、先ほど設定した変数があるので、この変数の右の欄に向かってPrefab化したPlayerBulletをドラッグ&ドロップで代入してあげます。

これをアウトレット接続とも呼びますが、public修飾子を付けて変数を宣言したので、インスペクターウィンドウ上からオブジェクトを直接代入することができるようになっています。

これで実際にゲームを実行してみましょう。

プレイヤーを移動しながら、Enterキーで弾を発射させることができるようになりました。

なお、前回も紹介したキー操作による入力や、transform.positionについては、以下の記事でもう少し詳しく解説していますので、参考にしてみてください。

(Clone)の表示を削除しておく

これで弾を撃つ設定は完了しましたが、弾が複製された際に「PlayerBullet(Clone)」(Clone)という表記が自動的に付いてしまいます。

このままでも問題無いのですが、後ほどこの弾のオブジェクト名を使って条件指定を作っていく予定なので、今回はこの(Clone)という表記を削除しておきたいと思います。

(Clone)を削除させるためには、先ほどのスクリプトPlayerShootの中に少し追加していきます。

using UnityEngine;

public class PlayerShoot : MonoBehaviour
{
    public GameObject playerBullet; // GameObject型の変数を宣言する

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Return))   // Enterキーを押した場合
        {
            GameObject cloneObject = Instantiate(playerBullet, this.transform.position, Quaternion.identity);  // 弾を表示させて座標を移動させる処理
            cloneObject.name = "PlayerBullet";  // 名前を変更する処理
        }
    }
}

11行目で、複製されるオブジェクト用のGameObject型の変数cloneObjectを宣言して初期化しています。

そして、Instantiate関数で複製したオブジェクトを、その変数に代入しておき、nameを使ってそのオブジェクト名を「PlayerBullet」という(Clone)を除いた名前に変更しておきます。

nameは、オブジェクト名を管理している変数で、今回はその変数を変更することでオブジェクト名を変えています。

これで再度ゲームを実行して弾を発射してみると、

(Clone)の表記が消えていると思います。

これで、プレイヤーが弾を発射するという処理が完成しました。

まとめ

このページでは、Enterキーを押すとプレイヤーから弾が発射されるという処理を作っていきました。

弾を発射させるためには、

という形で作っていきました。

弾が発射できるようになったら、次は当たり判定を作って敵を倒す処理を作っていきましょう。

最後までお読みいただきまして、ありがとうございました!

コメント