i-school - 【2Dサイドビュー】左右方向への弾の発射機能
 2Dサイドビューゲームの実装例です。

 プレイヤーの向いている方向に対して、左右方向に弾を撃ち分けて発射します。
弾の画像の向きは発射される方向に合わせるように制御します。






1.1つのスクリプトで制御する場合


 弾の生成と制御を同時に行うアプローチです。

 弾用のプレハブには Rigidbody2D コンポーネントとコライダーがアタッチされていれば問題ありません。
重力の設定、トリガーの設定などはゲームに応じて調整してください。



<参考画像>







 このスクリプトはプレイヤーにアタッチします。

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

public class BulletGenerator : MonoBehaviour
{
    // 弾のプレハブ
    public GameObject bulletPrefab;

    // 弾の速度
    public float bulletSpeed = 10f;

  // 弾の生成位置
    public Transform spawnPoint;


    void Update()
    {
        // Vが押されたら
        if (Input.GetKeyDown(KeyCode.V))
        {
      // 弾のプレハブのクローンを生成する
            GameObject bullet = Instantiate(bulletPrefab, spawnPoint.transform.position, Quaternion.identity);

            // プレイヤーの向きを取得
            float playerDirection = transform.localScale.x;
            Debug.Log(playerDirection);

            // 弾の初期速度を設定
            Rigidbody2D bulletRB = bullet.GetComponent<Rigidbody2D>();
            if (bulletRB != null)
            {
                Debug.Log(bulletSpeed * playerDirection);
                
                // プレイヤーの向きに応じて初期速度を設定
                bulletRB.velocity = new Vector2(bulletSpeed * playerDirection, 0f);
                
                // 画像の向きをキャラに合わせる
                Vector3 temp = bullet.transform.localScale;
                temp.x = transform.localScale.x;
                bullet.transform.localScale = temp;
            }
        }
    }
}



<参考画像>









<リファクタリング>


 ゲーム内に弾を生成する処理は、そのアクションの多さに比例して処理の負荷が高くなります。
そのため、完成した処理の見直しを行いつつ、効率化を図ることが大切です。

 設計部分を再構築したり、負荷のかかっている部分を見つけるなど、リファクタリングは多岐にわたります。



 今回の場合、プレハブをアサインする際のデータ型の情報を GameObject ではなく、Rigidbody2D に変更します。
このようにすることで、Instantiate メソッドの処理の部分も変更になります。

 Instantiate メソッドは、第1引数に指定したデータ型を元にプレハブをクローンする処理です。
このとき、プレハブにアタッチされているクラスであれば、いずれであってもクローンを生成出来ます。

 そのため、生成されたクローンが、その後、どのような制御を行う必要があるかを考えて、
それに合わせたデータ型で生成する方が効率化を図れます。

 今回であれば、生成後に Rigidbody2D コンポーネントを取得する必要があり、そのために GetComponent メソッドを行っていました。

 Instantiate メソッド、そして GetComponent メソッドは負荷の高い処理であるため、
いずれかの処理を無くしたり、あるいは、利用する回数を減らすことができれば、処理の負荷軽減を図ることが可能です。

 Instantiate メソッド自体はオブジェクトプールなどの機能を追加することで処理を代用し、処理の負荷軽減が可能ですが、
それは別途、機能の追加が必要になるため、今回は Instantiate メソッドは利用しつつ、その処理の戻り値になるデータ型を
GameObject 型から Rigidbody2D 型に変更しています。

 結果として、GetComponent メソッドの処理を省略した、効率的なアプローチが完成します。



 処理が簡略化されているとともに、GetComponent メソッドの処理も不要になっているので処理負荷の軽減も出来ています。


2.2つのスクリプトで制御する場合


 弾のプレハブに弾用のスクリプトをアタッチし、
弾の生成用のスクリプトと役割を分割したアプローチです。

 こちらの処理の方が柔軟性が高く、また、1つのスクリプト辺りの責務も少なくなります。


<1.弾のプレハブにアタッチするスクリプト>




<2.弾を生成するスクリプト>


 このスクリプトはプレイヤーにアタッチします。

 プレハブをアサインするための変数のデータ型を、Bullet クラスに指定している部分が重要です。
 


 このように分割することで、それぞれのクラスが独立して責務を果たせるようになります。
Bullet クラスは弾の挙動に関するロジックを持ち、BulletGenerator クラスは弾の生成に関するロジックを持ちます。

 また、Bullet クラスを利用して Instantiate メソッドを行っているため、
生成後にすぐに Bullet クラスに命令を出すことが出来ています(GetComponent メソッドの利用をなくして負荷軽減を図れています)



 以上になります。

 処理を読み解くことで、多彩な処理を記述出来るようになります。