🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

1031閲覧

シューティングゲームにおけるオブジェクトプールの作成について

hamu2000

総合スコア3

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2021/01/17 11:41

現在私はunity2Dでシューティングゲームを作成しています。
プレイヤーが打つ球をオブジェクトプールから作成したいのですがうまくいきません。
PlayerControllerの42にエラーがあるそうなのですが自分では解決できないため投稿しました。
参考サイト様:https://tama-lab.net/2018/06/%E3%80%90unity%E3%80%912d%E3%82%B7%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%82%B2%E3%83%BC%E3%83%A0%E3%81%A7%E8%BB%BD%E3%81%84%E5%87%A6%E7%90%86%E3%81%A7%E5%BC%BE%E3%82%92%E6%92%83/

public class BulletPool : MonoBehaviour
{
[SerializeField] //外部から値が変更できるようになる
private GameObject bulletpoolObj; // プールするオブジェクト。ここでは弾
private List<GameObject> bulletpoolObjList; // 生成した弾用のリスト。このリストの中から未使用のものを探したりする
private const int MAXCOUNT = 10; // 最初に生成する弾の数

void Awake() { CreatePool(); //Startと同時に実行 } // 最初にある程度の数、オブジェクトを作成してプールしておく処理 private void CreatePool() { bulletpoolObjList = new List<GameObject>(); //List作成 for (int i = 0; i < MAXCOUNT; i++) //球のMAX数まで繰り返す { var newObj = CreateNewBullet(); // 弾を生成 newObj.GetComponent<Rigidbody2D>().simulated = false; // 物理演算を切って(=未使用にして) bulletpoolObjList.Add(newObj); // リストに保存しておく } } // 未使用の弾を探して返す処理 // 未使用のものがなければ新しく作って返す public GameObject GetBullet() { // 使用中でないものを探して返す foreach (var obj in bulletpoolObjList) { var objrb = obj.GetComponent<Rigidbody2D>(); if (objrb.simulated == false) { objrb.simulated = true; //物理演算を加える(=使用) return obj; } } // 全て使用中だったら新しく作り、リストに追加してから返す var newObj = CreateNewBullet(); bulletpoolObjList.Add(newObj); newObj.GetComponent<Rigidbody2D>().simulated = true; return newObj; } // 新しく弾を作成する処理 private GameObject CreateNewBullet() { var pos = new Vector2(100, 100); // 画面外であればどこでもOK var newObj = Instantiate(bulletpoolObj, pos, Quaternion.identity); // 弾を生成しておいて newObj.name = bulletpoolObj.name + (bulletpoolObjList.Count + 1); // 名前を連番でつけてから return newObj; // 返す }

}

public class PlayerController : MonoBehaviour
{
//[SerializeField] //外部から値が変更できるようになる
//private GameObject burret; //弾のプレファブ。inspectorで指定する

private float shotDelay = 10f; //弾を打つ間隔 private Transform tf; private BulletPool pool; //ここ追加① void Start() { tf = this.transform; // 弾を打つコルーチンを呼び出す StartCoroutine(ShotBullet()); //コルーチン:指定した時間に処理を実行できる pool = GameObject.Find("BulletPool").GetComponent<BulletPool>(); } IEnumerator ShotBullet() //IEnumerator:非同期処理、コルーチンのために必要 { while (true) { // 弾を撃つ処理を呼んで Shot(); // shotDelay秒待つ yield return new WaitForSeconds(shotDelay); } } private void Shot() { // ここ追加③。プールから弾をもらう var burret = pool.GetBullet(); burret.transform.position = new Vector2(tf.position.x, tf.position.y); // 弾をプレイヤーと同じ位置/角度で作成 //Instantiate(burret, tf.position, tf.rotation); }

}

エラー
NullReferenceException: Object reference not set to an instance of an object
PlayerController.Shot () (at Assets/Scripts/PlayerController.cs:42)
PlayerController+<ShotBullet>d__4.MoveNext () (at Assets/Scripts/PlayerController.cs:31)
UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at <d1422b3fc93746018c92eda852993b93>:0)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
PlayerController:Start() (at Assets/Scripts/PlayerController.cs:21)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

NullReferenceExceptionは参照先見つからんってエラーなんで、まず疑うのはpoolが参照取れているかですかね。デバッグログを入れて確認してみてください。

cs

1private void Shot() 2{ 3// 参照先はあるか 4Debug.Log(pool); 5 6// ここ追加③。プールから弾をもらう 7var burret = pool.GetBullet(); 8burret.transform.position = new Vector2(tf.position.x, tf.position.y); 9// 弾をプレイヤーと同じ位置/角度で作成 10//Instantiate(burret, tf.position, tf.rotation); 11}

上がnullとかになっているようならコルーチン叩いたときに参照先がとれてないので、Startで参照を取得しているタイミングを変えてみてテストします。

cs

1void Start() 2{ 3tf = this.transform; 4pool = GameObject.Find("BulletPool").GetComponent<BulletPool>(); // メソッド叩く前に参照取得 5Debug.Log(pool); // 参照は取れたか確認 6 7// 弾を打つコルーチンを呼び出す 8StartCoroutine(ShotBullet()); //コルーチン:指定した時間に処理を実行できる 9 10//pool = GameObject.Find("BulletPool").GetComponent<BulletPool>(); 11}

投稿2021/01/18 00:31

hogefugapiyo

総合スコア3302

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問