Unityでゲーム制作！跳弾に挑戦した！

《環境メモ》
★Windows11 version 22H2
★Unity 2018.2.15f1

↓実際に動いている動画]
https://twitter.com/kazuma_tech/status/1597949450978496513

https://twitter.com/kazuma_tech/status/1597949450978496513

# 1.弾の作成
モデルは何でも可(自分はBlenderを使って作成しました)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2972750/faf77ae6-9ed9-a521-7296-8cf51ffc0908.png)

# 2.Unity上でPrefab化する
作った弾は、Unity上のファイルにPrefabとしてインポートしました

シーン上に空のオブジェクトを作成し、そのオブジェクトの子としてさっき作成した弾を格納します(z軸が飛んでいく方向になります)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2972750/13e675fa-1eaf-3163-53fb-366796d952d5.png)
↑Hierarchy上
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2972750/ddb74b90-a337-2644-0d3c-8fab6ee52432.png)

弾に当たり判定を適用していきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2972750/bdda1203-9a20-2ec2-1d2c-75878e39a9f7.png)
・Freeze Positionについては、勝手に上下しないようにするため
・弾を変な方向に曲げたくないので、FreezeRotationはすべてチェックしています
・Sphere Colliderの半径の大きさ、位置は弾の大きさと同じくらいに設定しました

# 3.弾の動きを作成
それでは弾の動きのコードになります

```C#:BulletMove.cs
using UnityEngine;

public class BulletMove : MonoBehaviour
{
    [SerializeField] private float Bulletspeed = 7.5f;    // Bulletの速さ
    [SerializeField] private int RefNumber = 2;           // 反射回数
    private int RefCount = 0;                             // 反射回数カウント用
    private Vector3 lastVelocity;                         // 速度ベクトル
    private Rigidbody rb;                                 // Rigidbody用

    void Start()
    {
        // コンポーネントを取得
        rb = GetComponent<Rigidbody>();

        // 初速
        rb.velocity = transform.forward * Bulletspeed;
    }

    private void Update()
    {
        // Rigidbodyを使用した移動用
        this.lastVelocity = this.rb.velocity;
    }

    void OnCollisionEnter(Collision col)
    {
        // 反射回数+1する
            RefCount++;

            // 指定回数反射しているなら弾は消滅
            if (RefCount == RefNumber)
            {
                Destroy(gameObject);
            }

            // 反射ベクトル計算
            Vector3 refrectVec = Vector3.Reflect(this.lastVelocity, col.contacts[0].normal);
            this.rb.velocity = refrectVec;

            // 弾を反射ベクトルの方向に向ける
            transform.LookAt(this.transform.position + refrectVec);
    }
```
反射回数をなくせば無限に反射できます

（解説）
`this.lastVelocity = this.rb.velocity;`はBulletが移動するためのコードで常に初速とその方向で運動します

肝心の跳弾ですが`refrectVec = Vector3.Reflect(this.lastVelocity,col.contacts[0].normal);`の行でベクトルを計算し、`transform.LookAt(this.transform.position + refrectVec);`で反映しています

> `Vector3.Reflect`の引用です

https://docs.unity3d.com/ja/2018.4/ScriptReference/Vector3.Reflect.html

> `transform.LookAt`の引用です

https://docs.unity3d.com/ja/2019.4/ScriptReference/Transform.LookAt.html

`transform.LookAt`ですが、そのまま`refrectVec`を入れると、Targetがずれるので、Bullet自身の座標を入れるようにしましょう

これで弾の動きの完成です！

# Ex.弾を撃つ方法
あとは弾を撃つ方法として

```C#:BulletMove.cs
using UnityEngine;

public class BulletShoot : MonoBehaviour
{
    [SerializeField] private GameObject Bullet;        // 発射する弾のオブジェクト
    [SerializeField] private Transform ShootPoint;     // 弾の出る位置

    void Update()
    {
        // 弾の発射(左クリック)
        if (Input.GetMouseButtonDown(0))
        {
            Instantiate(Bullet, ShootPoint.position, ShootPoint.rotation);
        }
    }
}
```

銃などの撃つ媒体に、このコードを持たせることでShootPointからBulletが発射されます

`Instantiate`は任意の場所に任意のオブジェクトを生成する関数だと思ってください！

以上になります！
拙い文章ですが、同じようなことをしたい人の参考になればと思います！

ここ違う！とか疑問点はコメントください！