Unityでパーティクルに当たり判定をつける3つの方法

Collision / Trigger / 擬似パーティクルの使い分け

Unity の Particle System は「見た目(ビジュアル)専用」の仕組みとして設計されており、パーティクル個々に Collider を付けることはできません。

しかし、Unity には 衝突イベントを検出する仕組みが用意されており、設定次第では「敵に当たったらヒット処理」「地面で跳ね返る」「当たった位置を取得する」など、ゲームとして必要な当たり判定が実現できます。

この記事では、Unity でパーティクルの当たり判定を行う 3つの手法をわかりやすく解説します。


1. Collision モジュールを使う(最も手軽な当たり判定)

概要

Particle System の Collision モジュールをオンにすると、パーティクルが Collider(3D/2D)にぶつかったことを取得できます。

最も簡単で、設定だけで動くため 演出中心のゲームでよく使われます。

設定方法

  1. パーティクルを選択
  2. Inspector → Collision を ON
  3. Type:World(シーンのコライダーを使う)
  4. Collides With:衝突させたい Layer を選択
  5. Send Collision Messages を ON(スクリプトでイベントを受け取る)

これだけで、パーティクルが物体に触れた瞬間を検出できます。

衝突イベントを受け取るスクリプト

パーティクルの GameObject に下記スクリプトを追加します。

using UnityEngine;

public class ParticleHitReceiver : MonoBehaviour
{
    private ParticleSystem ps;

    void Start()
    {
        ps = GetComponent<ParticleSystem>();
    }

    // パーティクル1粒でも触れたら呼ばれる
    void OnParticleCollision(GameObject other)
    {
        Debug.Log("パーティクルが衝突: " + other.name);
    }
}

特徴と注意点

  • パーティクルが Collider に “触れたら” 確実に呼ばれる
  • 大量に発生させると呼び出し回数も多くなる
  • 座標や粒子ごとの詳細までは取得できない

ヒット演出や軽いエフェクトに最適です。


2. Trigger モジュールで粒子ごとの当たり判定を取得する(高度な処理)

概要

Trigger モジュールでは、どのパーティクルが当たり領域に入ったか・出たかを粒子単位で取得できます。

座標を取得して処理したいときに便利で、魔法・ビーム・範囲攻撃の命中処理などでよく使われます。

設定手順

  1. Inspector → Trigger を ON
  2. Add Collider で判定したいコライダーを追加
  3. Enter / Exit / Inside / Outside などほしいイベントを有効化

粒子の座標を取得できるスクリプト

using UnityEngine;

public class ParticleTriggerExample : MonoBehaviour
{
    ParticleSystem ps;
    ParticleSystem.Particle[] particleBuffer;

    void Start()
    {
        ps = GetComponent<ParticleSystem>();
        particleBuffer = new ParticleSystem.Particle[ps.main.maxParticles];
    }

    void OnParticleTrigger()
    {
        // Inside に入っている粒子を取得
        int count = ps.GetTriggerParticles(ParticleSystemTriggerEventType.Inside, particleBuffer);

        for (int i = 0; i < count; i++)
        {
            Vector3 pos = particleBuffer[i].position;
            Debug.Log("Inside: " + pos);

            // 例:粒子を消す
            particleBuffer[i].remainingLifetime = 0;
        }

        ps.SetTriggerParticles(ParticleSystemTriggerEventType.Inside, particleBuffer, 0, count);
    }
}

できること

  • 粒子ごとの座標取得
  • 粒子の色変更・速度変更
  • 当たった粒子だけ消す
  • “どの粒子が入ったか” を判別可能

細かい判定をしたい場合はこちらが最適解です。


3. 弾丸としては「擬似パーティクル」を使う(実務でよく使う)

概要

シューティングゲームなど、正確な当たり判定が必要な場合はパーティクルではなく、小さなプレハブを飛ばす方式が推奨されます。

理由は以下の通りです:

  • パーティクルは高速移動で判定をすり抜けることがある
  • 粒子単位の衝突判定は重い
  • Rigidbody や Collider を使う物理処理の方が安定している
  • Object Pool と組み合わせることで高速

典型的な構成

  • 小さな Sprite/Quad
  • Rigidbody(2D/3D)
  • Collider(2D/3D)
  • ヒット時にエフェクトを生成(Particle を使用)

この方式は 見た目はパーティクル、実際の当たり判定はプレハブ という構成になります。

Unity の多くの市販ゲームもこの方式です。


4. どれを使うべき?(用途別に明確化)

やりたいこと推奨手法
火花・煙・魔法エフェクトが壁に触れたら反応させたいCollision
敵に当たった粒子だけ個別処理したいTrigger
弾丸・レーザー・投射物の当たり判定擬似パーティクル(Prefab)
パーティクルの位置を使ってヒット演出したいTrigger
爆発の煙が地面に触れたら散らしたいCollision

まとめ

Unity の Particle System は本来 “見た目の演出用” の機能ですが、Collision や Trigger モジュールを使うことで 十分ゲームに使える当たり判定を作れます。

  • 簡易判定 → Collision
  • 粒子単位の詳細判定 → Trigger
  • 正確な弾丸判定 → 擬似パーティクル(Prefab)

目的に合わせてこの3つを使い分けることがポイントです。


付録)各モジュール詳細

◆ Type

World / Planes のどちらを使うかを選ぶ。

  • Worldシーン内の 3D/2D Collider と衝突する。最も一般的な選択肢。
  • Planesパーティクル専用の「仮想平面」とだけ衝突させる。地面との接地演出などに使われる。

現在は World になっているので、シーン中の Collider との衝突が有効です。


◆ Mode(2D / 3D)

衝突判定の次元を選ぶ。

  • 3D → BoxCollider / MeshCollider / SphereCollider と衝突
  • 2D → BoxCollider2D / CircleCollider2D と衝突

現在は 3D なので、敵や壁なども 3D Collider を使う必要があります。


◆ Dampen

衝突したときの 速度減衰率

0 = 減衰なし

1 = 完全に停止

現在は 0 → ぶつかっても速度が落ちません。


◆ Bounce

衝突時にどれだけ跳ね返るか。

0 = 跳ね返らない(吸収)

1 = 反射する

“跳ね返る火花” 演出などで使用。


◆ Lifetime Loss

衝突時に 寿命をどれだけ削るか

0 = 減らさない

1 = 即死

衝突で煙が減衰する演出などに使える。


◆ Min Kill Speed / Max Kill Speed

一定速度以下(または以上)になったとき、粒子を消す(Kill)する速度しきい値。

  • Min Kill Speedこれより遅くなったら粒子を消す
  • Max Kill Speedこれより速くなったら粒子を消す

火花が減速したら消える、といった制御に使える。


◆ Radius Scale

粒子の当たり判定の「見かけサイズ」を変更。

  • 1 = 通常
  • 2 = 倍の大きさとして判定
  • 0.5 = 半分の大きさ

粒子が高速で小さいと衝突しにくいため、すり抜け防止に使われる。


◆ Collision Quality

衝突判定の精度。

  • High:最も正確(重い)
  • Medium:標準
  • Low:高速だが衝突抜けが起こりやすい

高速パーティクルは High 推奨


◆ Collides With

衝突対象の Layer を選ぶ。

例:

  • Player のみ
  • Ground のみ
  • Everything(全部)

現在は Everything なので全レイヤーと当たります。


◆ Max Collision Shapes

パーティクルが一度に扱う衝突対象数の上限。

デフォルト256。

巨大な MeshCollider が多数あるシーンでは増やすこともある。


◆ Enable Dynamic Colliders

動くオブジェクトの Collider も衝突対象にする

✔ = ON(推奨)

OFFにすると静的ジオメトリとしか当たらない。


◆ Collider Force

衝突時にパーティクルが “相手に与える力”。

0 → 力を与えない

数値を上げると、パーティクルが物体を押すようになる

※多くのゲームでは 0 のまま。


◆ Multiply by Collision Angle / Speed / Size

Collider Force の計算に使う補正項目。

  • Collision Angle衝突角度によって力を変える
  • Particle Speed粒子スピードで力を変える
  • Particle Size粒子サイズで力を変える

物理挙動をリアルにしたい場合に使う。

通常のエフェクト用途では不要。


◆ Send Collision Messages

衝突イベント(OnParticleCollision)を発生させるスイッチ。

✔ ON → スクリプトが衝突を受け取る

✘ OFF → 何も呼ばれない(衝突していても)

現在は OFF

→ ブログで書いた「パーティクルで当たり判定を取る」には 必ず ON にする必要あり


◆ Scene Tools → Visualize Bounds

パーティクルの「当たり判定境界」を SceneViewに線で表示。

デバッグ時のみ使う。

普段は OFF のままでOK。


Trigger モジュールは、特定のコライダー領域に入った・出た粒子を検出できる機能です。

Collision モジュールよりも「粒子単位での細かい制御」が可能です。

スクショの項目を上から順に解説します。


◆ List(コライダーリスト)

表示:List is Empty

ここに「パーティクルが判定対象とする Collider」を追加します。

追加方法:

+ ボタン → シーン内の 3D/2D Collider を指定

重要ポイント

  • ここが空のままだと Trigger イベントは一切発生しない
  • Collision とは異なり、Trigger は 自動で Collider を拾わない

必ず、判定したい Collider を追加する必要があります。


◆ Inside

粒子が「登録したコライダーの内部にいる間」どうするかを指定。

選択肢:

オプション動作
Ignore何もしない
Kill粒子を消す
Callbackスクリプトに通知する(GetTriggerParticles で取得)

スクショでは Kill

→ 粒子が内部に入った瞬間、寿命関係なく消滅します。


◆ Outside

粒子が「コライダーの外側にいる間」にどうするか。

通常は Ignore(何もしない)で OK。


◆ Enter

粒子がコライダーの外 → 内に入った瞬間の動作。

オプション動作
Ignore何もしない
Kill侵入した瞬間に粒子を消す
Callbackスクリプトへ通知

攻撃判定やヒット演出では Callback を使うことが多い。


◆ Exit

粒子が「コライダーから出た瞬間」の処理。

外へ出た際の反応が必要なときだけ使用する。

通常の敵ヒット判定では使わない。


◆ Collider Query Mode

粒子座標の取得方法や判定方法を変更できる高度設定。

Mode意味
Disabled粒子の位置情報は取らない(高速)
OneWayコライダーの片側のみを計算
TwoWay片側+裏側(両面)を判定
Distance粒子と Collider の距離に基づいて高精度で判定

スクショは Disabled

→ 速度優先。粒子位置の取得(粒子操作)を行わない設定。


◆ Radius Scale

粒子の当たり判定のサイズを補正。

  • 1 = 標準
  • 2 = 2倍
  • 0.5 = 半分

高速粒子のすり抜けを防ぎたいときに 1.2〜1.5 に上げることがある。

現在は 1(標準)


◆ Visualize Bounds

トリガー判定の「境界線」をシーンビューに可視化。

デバッグ用途。

普段は OFF で問題なし。


◆ まとめ(スクショ設定が意味すること)

あなたのスクショの設定はこういう動作になります:

  • コライダーリストは 空のため、現在は何も判定されない
  • Inside = Kill → コライダー内部に入った粒子を即消す設定
  • Enter / Exit / Outside は Ignore → スクリプト通知なし
  • Collider Query Mode = Disabled → 粒子情報は使わない
  • Radius Scale = 1 → 標準サイズ

つまり、現状は 「何かのコライダーを追加して内部に入った粒子を消す」だけの設定です。


◆ Trigger モジュールを「当たり判定として使う」正しい設定例

例:粒子が敵に当たった瞬間だけ処理したい

Inside:Ignore  
Enter:Callback  
Exit:Ignore  
Outside:Ignore  
Collider Query Mode:TwoWay  
Radius Scale:1.2  

スクリプトでは:

void OnParticleTrigger()
{
    int count = ps.GetTriggerParticles(ParticleSystemTriggerEventType.Enter, particles);
    for (int i = 0; i < count; i++)
    {
        Vector3 pos = particles[i].position;
        Debug.Log("Hit at " + pos);
    }
}
訪問数 4 回, 今日の訪問数 4回

Particle,Unity

Posted by hidepon