Particle Systemで爆弾を作る

この記事ではUnityのParticle Systemを用いて爆弾を実装することによって、Particle Systemの理解を深めます。動作環境はUnity2022.3.10fです。

# オブジェクトの配置
Hierarchyウィンドウで右クリックして3D ObjectからPlaneとSphereを選択します。Planeは地面で、Sphereは爆弾とします。地面に爆弾を落として爆発する動きを再現したいのでSphereはPlaneの上に配置します。自分の環境では下の画像のような感じで配置しました。
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3644510/bf0a98c2-8c4d-809d-27b7-a61e274a1346.png)

Planeは、InspectorウィンドウからTagの名前をGroundに設定してください。
また、Hierarchyウィンドウで右クリックしてEffects→Particle Systemを選択してエフェクトを作成しておきます。作成出来たらProjectウィンドウにドラッグしてPrefab化しておきます。

# 爆発のエフェクト
C#スクリプトによって地面に落ちたら爆発させる処理と爆風のエフェクトの処理を実装します。Particle SystemはInspectorウィンドウからも各パラメータを調整できますが、理解を深めるために今回はスクリプトによって制御します。以下のスクリプトを作成して爆弾のオブジェクトSphereにアタッチします。

```C#:Bomb.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Rigidbody))] //Rigidbodyをアタッチして爆弾を自然落下させる
public class Bomb : MonoBehaviour
{
    public ParticleSystem particle;

    void Start()
    {
        GetComponent<Renderer>().material.color = Color.black;
        particle.startColor = new Color32(255, 25, 0, 255); //パーティクルの色を変更
        particle.startSize = 5.0f; //パーティクルのサイズを変更
        particle.startLifetime = 1.0f; //パーティクルの生存時間を変更
        particle.emission.SetBursts(
            new ParticleSystem.Burst[]
            {
                new ParticleSystem.Burst(0, 300) //パーティクルの発生個数を300個に設定
            });

        var main = particle.main;
        main.loop = false; //パーティクルの発生をループさせない
        main.duration = 1.0f; //パーティクルを発生させる時間を変更
        
        //パーティクルを球状に放出する
        var shape = particle.shape;
        shape.shapeType = ParticleSystemShapeType.Sphere;

        //パーティクルの当たり判定を有効にする
        var collision = particle.collision;
        collision.enabled = true;
        collision.type = ParticleSystemCollisionType.World;
        collision.sendCollisionMessages = true;
    }

    void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            Explode(); //爆弾が地面に当たったら爆発させる
        }
    }

    void Explode()
    {
        GetComponent<Renderer>().material.color = new Color32(255, 25, 0, 255);
        Instantiate(particle, this.transform.position, Quaternion.identity); //パーティクルを発生させる
        Destroy(this.gameObject, 0.5f); //0.5秒後に爆弾のオブジェクトを消滅させる
    }
}
```

Sphereにスクリプトをアタッチしたら、InspectorウィンドウでParticleにPrefab化しておいたParticle Systemをドラッグします。
これを実行すると爆発の炎のようなエフェクトが発生します。以下の図は自分の環境で試した結果です。
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3644510/ca4926b9-3989-f3b0-1803-936700a7d3e8.png)

実際のゲームで見られる爆発のエフェクトから比べるとかなり雑な作りです。今回はParticle Systemを理解するためにUnityの標準機能とC#スクリプトでエフェクトを作成しましたが、リアルな爆炎を再現するならAsset Storeで専用のエフェクトを探す方が良いと思います。

# 爆発によるアクション
爆風のエフェクトが発生するようになったので、次は爆発で周りのオブジェクトにアクションが起きるように実装します。具体的には爆風で障害物が吹き飛ばされ、敵は消滅するようにします。以下のスクリプトを作成してPrefab化したParticle Systemにアタッチします。

```C#:Explosion.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Explosion : MonoBehaviour
{
    Rigidbody rb;

    void OnParticleCollision(GameObject collision)
    {
        if (collision.CompareTag("Block"))
        {
            rb = collision.GetComponent<Rigidbody>();
            Vector3 direction = collision.transform.position - this.transform.position; //吹き飛ばす方向を設定
            rb.AddForce(direction, ForceMode.Impulse); //Blockタグが付いたオブジェクトを吹き飛ばす
        }
        
        if (collision.CompareTag("Enemy"))
        {
            Destroy(collision.gameObject); //Enemyタグが付いたオブジェクトを消滅させる
        }
    }
}
```
パーティクルの当たり判定の関数は、OnCollisionEnterではなくOnParticleCollisionを使用することに注意しましょう。
変数directionは吹き飛ばす方向を決める3Dベクトルです。オブジェクトを吹き飛ばす処理は色々な実装方法があると思いますが、今回の記事ではパーティクルからパーティクルと衝突したオブジェクトへのベクトルを取得し、AddForceの引数に代入しています。これで爆発の中心から外側に向かって瞬間的な力が加わります。
次に、爆風を当てる対象となる障害物や敵キャラクターのオブジェクトを用意します。オブジェクトはHierarchyウィンドウから3D Objectを生成したり、Asset Storeから持ってきたりして用意しましょう。それらをPlane上で爆弾の着弾地点付近に配置します。配置したオブジェクトには、InspectorウィンドウからTagの名前をBlockまたはEnemyに設定します。衝突判定のためのColliderも忘れずアタッチしましょう。
これで実行すると爆風に当たったオブジェクトは、TagがBlockのものは吹き飛ばされ、TagがEnemyのものは消滅します。

# 参考
https://creator.cluster.mu/2023/04/19/explosion_particle/
https://bravememo.hatenablog.com/entry/2020/01/28/071402
https://www.ame-name.com/archives/109
https://mono-pro.net/archives/10121

# 公式リファレンス
https://docs.unity3d.com/ScriptReference/ParticleSystem.MainModule.html
https://docs.unity3d.com/ScriptReference/ParticleSystem.EmissionModule.html
https://docs.unity3d.com/ScriptReference/ParticleSystem.CollisionModule.html