Unityで銃を撃つ #8 弾数を表示する

投稿者: | 2020-01-15


弾数を表示します。0になると弾を発射できなくなり、リロードすると弾数が増えて撃てるようになります。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.AI;
  5. using UnityEngine.UI;
  6.  
  7. public class GunScript : MonoBehaviour
  8. {
  9. public ParticleSystem gunParticle;
  10. public GameObject gunLight;
  11.  
  12. public Animator gunAnimator;
  13.  
  14. public float rate = 0.075f;
  15.  
  16. public GameObject bullet;
  17. public GameObject playerFace;
  18. public float power;
  19.  
  20. public GameObject Zombie;
  21. public GameObject Ragdoll;
  22. List<GameObject> zombieList;
  23.  
  24. public GameObject player;
  25.  
  26. public static GameObject girlRagdoll;
  27. Camera playerCamera;
  28.  
  29. const int magazineSize = 30;
  30. const int allBullets = 150;
  31.  
  32. int currentMagazine = magazineSize; // 現在のマガジンの弾数
  33. int remaining; // 残りの弾数
  34.  
  35. public Text bulletText; // 弾数を表示するテキスト
  36.  
  37. // Start is called before the first frame update
  38. void Start()
  39. {
  40. remaining = allBullets - currentMagazine;
  41.  
  42. zombieList = new List<GameObject>();
  43. StartCoroutine("GenarateZombie");
  44. playerCamera = playerFace.GetComponent<Camera>();
  45.  
  46. girlRagdoll = Ragdoll;
  47.  
  48. bulletText.text = currentMagazine.ToString();
  49. }
  50.  
  51. // Update is called once per frame
  52. void Update()
  53. {
  54.  
  55. // default状態で、マウス左クリックを押した時
  56. if (Input.GetMouseButtonDown(0) && currentMagazine > 0 && gunAnimator.GetCurrentAnimatorStateInfo(0).IsName("defualt")) // ママ
  57. {
  58. gunParticle.Play(); // パーティクルの再生
  59. gunAnimator.SetTrigger("Shoot");
  60.  
  61. StartCoroutine("Shoot");
  62.  
  63. }
  64. // MachineGin_shoot状態で、マウス左クリックを離した時
  65. else if (Input.GetMouseButtonUp(0) && gunAnimator.GetCurrentAnimatorStateInfo(0).IsName("MachineGin_shoot"))
  66. {
  67.  
  68. gunParticle.Stop(); // パーティクルの停止
  69. gunAnimator.SetTrigger("Shoot");
  70. StopCoroutine("Shoot");
  71.  
  72. }
  73.  
  74. if (Input.GetKeyDown(KeyCode.T)) // Tキーを押した時
  75. {
  76. gunLight.SetActive(!gunLight.activeSelf); // ライトのオンオフ
  77. }
  78.  
  79. if (Input.GetKeyDown(KeyCode.R))
  80. {
  81. if (gunParticle.isPlaying)
  82. gunParticle.Stop(); // パーティクルの停止
  83.  
  84. gunAnimator.SetTrigger("DoReload"); // リロード状態に遷移させる
  85.  
  86.  
  87. }
  88.  
  89. // リロードが終わったら
  90. if (gunAnimator.GetCurrentAnimatorStateInfo(0).IsName("MachineGun_reload") && gunAnimator.GetCurrentAnimatorStateInfo(0).normalizedTime >= 1)
  91. {
  92. gunAnimator.SetTrigger("DoReload"); // リロード状態からデフォルトに遷移させる
  93.  
  94. currentMagazine = magazineSize; // マガジンを一杯にする
  95. bulletText.text = currentMagazine.ToString(); // 弾数を表示
  96. }
  97.  
  98.  
  99.  
  100. if (Input.GetMouseButton(1) && gunAnimator.GetCurrentAnimatorStateInfo(1).normalizedTime >= 1 && (gunAnimator.GetCurrentAnimatorStateInfo(1).IsName("LookInAnimation2") || gunAnimator.GetCurrentAnimatorStateInfo(1).IsName("New State")))
  101. {
  102. //覗き込む
  103.  
  104. gunAnimator.SetTrigger("LookIn");
  105. playerCamera.fieldOfView = 45f;
  106. }
  107. else if (!Input.GetMouseButton(1) && gunAnimator.GetCurrentAnimatorStateInfo(1).normalizedTime >= 1 && gunAnimator.GetCurrentAnimatorStateInfo(1).IsName("LookInAnimation"))
  108. {
  109. //覗き込むのをやめる
  110.  
  111. gunAnimator.SetTrigger("LookIn");
  112. playerCamera.fieldOfView = 60f;
  113. }
  114.  
  115.  
  116. }
  117.  
  118. private IEnumerator Shoot() // 弾を連射するコルーチン
  119. {
  120. while (currentMagazine > 0) // マガジンに弾があれば弾を発射し続ける
  121. {
  122. Instantiate(bullet, playerFace.transform.position, playerFace.transform.rotation).GetComponent<Rigidbody>().AddForce(playerFace.transform.forward * power, ForceMode.Impulse);
  123. currentMagazine--; // 弾を一個減らす
  124. bulletText.text = currentMagazine.ToString(); // 弾数を表示
  125.  
  126. if (currentMagazine <= 0) // マガジンに弾がなくなった時
  127. {
  128. gunParticle.Stop(); // パーティクルの停止
  129.  
  130. if (Input.GetMouseButton(0)) // 弾を発射していたら
  131. {
  132. gunAnimator.SetTrigger("Shoot"); // 発射のアニメーションを止める
  133. }
  134.  
  135. yield break; // コルーチンを終了
  136. }
  137.  
  138. yield return new WaitForSeconds(rate);
  139. }
  140. }
  141.  
  142. private IEnumerator GenarateZombie() // 1秒ごとにゾンビを生成するコルーチン
  143. {
  144. while (true)
  145. {
  146. zombieList.Add(Instantiate(Zombie,new Vector3(Random.Range(-88,88),0f,Random.Range(-88,88)),transform.rotation)); // ゾンビをランダムの位置に生成
  147. zombieList[zombieList.Count - 1].GetComponent<ZombieScript>().player = player;
  148.  
  149. yield return new WaitForSeconds(1);
  150. }
  151. }
  152. }

弾を発射するコルーチンの中でwhile文で銃弾の発射を繰り返しますが、現在のマガジンが0より大きいという条件を付けました。
弾を発射するたびに現在のマガジンの弾数を1つ減らして、弾数を画面に表示しています。

マガジンの弾が0になったらマズルフラッシュのエフェクトを停止して、「Shoot」パラメータをセットすることで、銃が振動するようなアニメーションを止めます。
この SetTrigger(“Shoot”) は弾を発射しているときに、マウスの左クリックを離したときにも使われますが、条件に GetCurrentAnimatorStateInfoメソッドを使って、弾を発射するステートにいるときだけ実行されるようにしているので、マウスの左クリックを押しながらリロードが終わった後に左クリックを離しても、再度「Shoot」パラメータがセットされることはありません。

リロードが終わったことを Animator.GetAnimatorTransitionInfo で知ろうと思ったのですがうまく動きませんでした。
https://docs.unity3d.com/ja/2017.4/ScriptReference/Animator.GetAnimatorTransitionInfo.html

リロード状態からデフォルトへの遷移はパラメータを使わずに、Has Exit Timeを使って時間が立つと自動で遷移するようにしていましたが、リロード状態にいる時に、アニメーションの再生が終わったらという条件がうまくいかなかったので、この遷移でも「DoReload」トリガーを使ってHas Exit Timeを使わずにスクリプトから遷移させるようにしました。

アニメーションが最後まで再生されたかどうかを知るには、GetCurrentAnimatorStateInfo(0).normalizedTimeを使っています。

  1. if (gunAnimator.GetCurrentAnimatorStateInfo(0).IsName("MachineGun_reload") && gunAnimator.GetCurrentAnimatorStateInfo(0).normalizedTime >= 1)
  2. {
  3. gunAnimator.SetTrigger("DoReload"); // リロード状態からデフォルトに遷移させる
  4.  
  5. currentMagazine = magazineSize; // マガジンを一杯にする
  6. bulletText.text = currentMagazine.ToString(); // 弾数を表示
  7. }

次は全体の弾数に制限をかけて、それが0になるとリロードできないようにしてみます。

コメントを残す

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