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

投稿者: | 2020-01-15


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

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.UI;

public class GunScript : MonoBehaviour
{
    public ParticleSystem gunParticle;
    public GameObject gunLight;

    public Animator gunAnimator;

    public float rate = 0.075f;

    public GameObject bullet;
    public GameObject playerFace;
    public float power;

    public GameObject Zombie;
    public GameObject Ragdoll;
    List<GameObject> zombieList;

    public GameObject player;

    public static GameObject girlRagdoll;
    Camera playerCamera;

    const int magazineSize = 30;
    const int allBullets = 150;

    int currentMagazine = magazineSize; // 現在のマガジンの弾数
    int remaining; // 残りの弾数

    public Text bulletText; // 弾数を表示するテキスト

    // Start is called before the first frame update
    void Start()
    {
        remaining = allBullets - currentMagazine;

        zombieList = new List<GameObject>();
        StartCoroutine("GenarateZombie");
        playerCamera = playerFace.GetComponent<Camera>();

        girlRagdoll = Ragdoll;

        bulletText.text = currentMagazine.ToString();
    }

    // Update is called once per frame
    void Update()
    {

        // default状態で、マウス左クリックを押した時
        if (Input.GetMouseButtonDown(0) && currentMagazine > 0 && gunAnimator.GetCurrentAnimatorStateInfo(0).IsName("defualt")) // ママ
        {
            gunParticle.Play(); // パーティクルの再生
            gunAnimator.SetTrigger("Shoot");

            StartCoroutine("Shoot");

        }
        // MachineGin_shoot状態で、マウス左クリックを離した時
        else if (Input.GetMouseButtonUp(0) && gunAnimator.GetCurrentAnimatorStateInfo(0).IsName("MachineGin_shoot"))
        {

            gunParticle.Stop(); // パーティクルの停止
            gunAnimator.SetTrigger("Shoot");
            StopCoroutine("Shoot");

        }

        if (Input.GetKeyDown(KeyCode.T)) // Tキーを押した時
        {
            gunLight.SetActive(!gunLight.activeSelf); // ライトのオンオフ
        }

        if (Input.GetKeyDown(KeyCode.R))
        {
            if (gunParticle.isPlaying)
                gunParticle.Stop(); // パーティクルの停止

            gunAnimator.SetTrigger("DoReload"); // リロード状態に遷移させる


        }

        // リロードが終わったら
        
        if (gunAnimator.GetCurrentAnimatorStateInfo(0).IsName("MachineGun_reload") && gunAnimator.GetCurrentAnimatorStateInfo(0).normalizedTime >= 1)
        {
            gunAnimator.SetTrigger("DoReload"); // リロード状態からデフォルトに遷移させる

            currentMagazine = magazineSize; // マガジンを一杯にする
            bulletText.text = currentMagazine.ToString(); // 弾数を表示
        }

        


        if (Input.GetMouseButton(1) && gunAnimator.GetCurrentAnimatorStateInfo(1).normalizedTime >= 1 && (gunAnimator.GetCurrentAnimatorStateInfo(1).IsName("LookInAnimation2") || gunAnimator.GetCurrentAnimatorStateInfo(1).IsName("New State")))
        {
            //覗き込む

            gunAnimator.SetTrigger("LookIn");
            playerCamera.fieldOfView = 45f;
        }
        else if (!Input.GetMouseButton(1) && gunAnimator.GetCurrentAnimatorStateInfo(1).normalizedTime >= 1 && gunAnimator.GetCurrentAnimatorStateInfo(1).IsName("LookInAnimation"))
        {
            //覗き込むのをやめる

            gunAnimator.SetTrigger("LookIn");
            playerCamera.fieldOfView = 60f;
        }


    }

    private IEnumerator Shoot() // 弾を連射するコルーチン
    {
        while (currentMagazine > 0) // マガジンに弾があれば弾を発射し続ける
        {        
            Instantiate(bullet, playerFace.transform.position, playerFace.transform.rotation).GetComponent<Rigidbody>().AddForce(playerFace.transform.forward * power, ForceMode.Impulse);
            currentMagazine--; // 弾を一個減らす
            bulletText.text = currentMagazine.ToString(); // 弾数を表示

            if (currentMagazine <= 0) // マガジンに弾がなくなった時
            {
                gunParticle.Stop(); // パーティクルの停止

                if (Input.GetMouseButton(0)) // 弾を発射していたら
                {
                    gunAnimator.SetTrigger("Shoot"); // 発射のアニメーションを止める
                }

                yield break; // コルーチンを終了
            }

            yield return new WaitForSeconds(rate);
        }
    }

    private IEnumerator GenarateZombie() // 1秒ごとにゾンビを生成するコルーチン
    {
        while (true)
        {
            zombieList.Add(Instantiate(Zombie,new Vector3(Random.Range(-88,88),0f,Random.Range(-88,88)),transform.rotation)); // ゾンビをランダムの位置に生成
            zombieList[zombieList.Count - 1].GetComponent<ZombieScript>().player = player;

            yield return new WaitForSeconds(1);
        }
        
    }
}

弾を発射するコルーチンの中で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を使っています。

if (gunAnimator.GetCurrentAnimatorStateInfo(0).IsName("MachineGun_reload") && gunAnimator.GetCurrentAnimatorStateInfo(0).normalizedTime >= 1)
{
    gunAnimator.SetTrigger("DoReload"); // リロード状態からデフォルトに遷移させる

    currentMagazine = magazineSize; // マガジンを一杯にする
    bulletText.text = currentMagazine.ToString(); // 弾数を表示
}

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

コメントを残す

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