Unityで銃を撃つ #4 銃弾を連射する

投稿者: | 2020-01-04

銃弾を連射するにはコルーチンを使います。

private IEnumerator Shoot()
{
    while (true)
    {
        yield return new WaitForSeconds(rate);

        Instantiate(bullet, playerFace.transform.position, playerFace.transform.rotation).GetComponent<Rigidbody>().AddForce(playerFace.transform.forward * power,ForceMode.Impulse);

           
    }
}

コルーチンの中でwhile文で銃弾を生成して発射する処理を繰り返します。マウス左クリックを押したときにこのコルーチンをスタートします。

WaitForSeconds()に連射する間隔を秒数のfloat値で入れることで連射速度を設定できます。

銃弾の発射速度

弾をAddForceで発射するときの力の強さで発射速度をコントロールしています。力の強さはインスペクタから設定しています。

実際の銃弾の速さに合わせるのは難しいようです。

弾を発射する位置と向き

銃弾は銃口からではなく、画面の真ん中からカメラが向く方へまっすぐ発射しています。
普通のFPSゲームでも壁に向かって至近距離で腰だめ撃ちしても目の前に銃痕が付くのでこれで良いと思います。

銃弾を作る

銃弾はBlenderで適当に作ってUnityに持ってきました。

Rigidbodyを付けて、Collision DetectionをContinuous Dynamicにします。

こうしないと銃弾が壁などをすり抜けます。

Sphereコライダーもつけました。

銃弾を破壊する

銃弾にスクリプトを付けて、時間が立ったり、何かに衝突したりしたときに銃弾が破壊されるようにしました。

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

public class BulletScript : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine("destroyBullet");
    }

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

    }

    private IEnumerator destroyBullet()
    {   
        yield return new WaitForSeconds(0.5f);
        Destroy(gameObject);
    }

    private void OnCollisionEnter(Collision collision)
    {
        Destroy(gameObject);
    }
}

Unityで銃を撃つ #4 銃弾を連射する」への4件のフィードバック

  1. 最初のスクリプトどうやって追加するんですか

    返信
      1. すいませんうまくできません。どの部分が弾を発射するスクリプトですか

        返信
        1. nekoromorph 投稿作成者

          銃のスクリプトで弾をインスタンス化して、弾のリジッドボディに力を加えることで発射しています。
          その後、銃弾がプレイヤーに衝突してすぐに消えるので、両方にレイヤーを付けて衝突を無視しています。こちらの記事の下部の方法です。

          // 銃のスクリプト
          using System.Collections;
          using System.Collections.Generic;
          using UnityEngine;
          
          public class GunScript : MonoBehaviour
          {
          
              [SerializeField] BulletScript bullet; // 銃弾のプレハブ
          
              // Start is called before the first frame update
              void Start()
              {
                  
              }
          
              // Update is called once per frame
              void Update()
              {
                  // 左クリックを押した時
                  if(Input.GetMouseButtonDown(0))
                  {
                      // コルーチンを開始
                      StartCoroutine("Shoot");
                  }
          
                  // 左クリックを離した時
                  if (Input.GetMouseButtonUp(0))
                  {
                      // コルーチンを停止
                      StopCoroutine("Shoot");
                  }
              }
          
              private IEnumerator Shoot()
              {
                  while (true)
                  {
                      yield return new WaitForSeconds(0.05f);
          
                      // 弾をインスタンス化
                      GameObject b = Instantiate(bullet.gameObject, Camera.main.transform.position, Camera.main.transform.rotation * bullet.gameObject.transform.rotation);
          
                      // Rigidbodyを取得
                      Rigidbody rb = b.GetComponent<Rigidbody>();
          
                      // 弾を発射
                      rb.AddForce(Camera.main.transform.forward * 40f, ForceMode.Impulse); 
          
                  }
              }
          }
          返信

コメントを残す

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