【Unity】銃弾のオブジェクトを再利用する #1

投稿者: | 2021-04-18

弾の種類を切り替えるで作った銃弾のオブジェクトを配列に入れて、順番に再利用してみました。

まずマガジンのクラスに銃弾のオブジェクトの配列を作りました。そして、銃を撃つとき、配列に空きがあれば銃弾をインスタンス化し、空きがなければ配列にあるものを順番に再利用します。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. public class Magazine : MonoBehaviour
  6. {
  7. [SerializeField] Bullet bullet;
  8. [SerializeField] int count = 20;
  9. Bullet[] bullets;
  10. [SerializeField] int poolSize = 10;
  11. int index;
  12.  
  13. private void Awake()
  14. {
  15. // 銃弾の配列を作る
  16. bullets = new Bullet[poolSize];
  17. }
  18.  
  19. public int GetCount()
  20. {
  21. return count;
  22. }
  23.  
  24. public bool Shoot()
  25. {
  26. // 弾が残っているとき
  27. if (count > 0)
  28. {
  29. // 配列に空きがあるとき
  30. if (bullets[bullets.Length - 1] == null)
  31. {
  32. Debug.Log(this + ": index = " + index + " 新規作成");
  33.  
  34. // 弾をカメラの前にインスタンス化する
  35. bullets[index] = Instantiate(bullet, Player2.GetInstance().transform.position + Player2.GetInstance().transform.forward * 1.5f, Player2.GetInstance().transform.rotation).GetComponent<Bullet>();
  36.  
  37. }
  38. // 空きがないとき
  39. else
  40. {
  41. Debug.Log(this + ": index = " + index + " 再利用");
  42. // 弾を止める
  43. bullets[index].Stop();
  44.  
  45. // 弾をカメラの前に移動
  46. bullets[index].SetPosition(Player2.GetInstance().transform.position + Player2.GetInstance().transform.forward * 1.5f);
  47.  
  48. }
  49.  
  50. // 発射する
  51. bullets[index].Shoot(Player2.GetInstance().transform.forward);
  52.  
  53. // インデックスを更新
  54. index = index >= poolSize - 1 ? 0 : index + 1;
  55. // 残弾数を減らす
  56. count--;
  57. GameScript3.GetInstance().SetBulletCount(this);
  58.  
  59. return true;
  60. }
  61. else
  62. {
  63. return false;
  64. }
  65. }
  66. }

再利用するとき、位置を移動して再度力を加えるだけでは、力を加える前の速度が銃弾に残っているので、変な方向に飛びます。

なので、銃弾の速度をゼロにしてから力を加えています。

配列の銃弾を順番に取得するために、int型の変数を使っています。これらはマガジン毎に作られます。

銃弾のクラスでは、発射や停止、移動のメソッドを定義しています。インスタンス化されて時間が立つと銃弾が削除されるようにしていましたが止めています。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. [RequireComponent(typeof(Rigidbody))]
  6. [RequireComponent(typeof(Collider))]
  7. public class Bullet : MonoBehaviour
  8. {
  9. [SerializeField] float power = 20f;
  10. Rigidbody rb;
  11. // Start is called before the first frame update
  12. void Awake()
  13. {
  14. rb = GetComponent<Rigidbody>();
  15. }
  16.  
  17. // 発射する
  18. public void Shoot(Vector3 dir)
  19. {
  20.  
  21. if (rb != null)
  22. {
  23. rb.AddForce(dir * power, ForceMode.Impulse);
  24. }
  25. }
  26.  
  27. // 銃弾の速度をゼロにする
  28. public void Stop()
  29. {
  30.  
  31. if (rb != null)
  32. {
  33. rb.velocity = default;
  34. rb.angularVelocity = default;
  35. }
  36. }
  37.  
  38. // 位置を移動する
  39. public void SetPosition(Vector3 pos)
  40. {
  41. transform.position = pos;
  42. }
  43.  
  44. }

これでマガジン毎に簡単に銃弾を再利用できました。

この方法だと、マガジンの種類が増えれば銃弾の配列も増えます。

コメントを残す

メールアドレスが公開されることはありません。