Version: 2020.2
言語: 日本語
Collision モジュール
Sub Emitters モジュール

Triggers モジュール

ビルトインパーティクルシステムの Triggers モジュールでは、シーンの 1 つまたは複数のコライダーとの相互作用に基づいてパーティクルにアクセスし、修正することができます。このモジュールを有効にすると、パーティクルシステムはアタッチされたスクリプトで OnParticleTrigger() コールバックを呼び出します。このコールバックを使って、シーンのコライダーに対する位置に応じてパーティクルのリストにアクセスできます。

パーティクルシステム Triggers モジュール
パーティクルシステム Triggers モジュール

Triggers モジュールの使用

まず、パーティクルが相互作用できるシーンのコライダーを指定します。そのためには、 コライダー のリストプロパティに 1 つ以上のコライダーを割り当てます。リスト内のコライダー数を増やすには、コライダーのリストの下にある + ボタンをクリックします。リストからコライダーを削除するには、コライダーを選択して - ボタンをクリックします。リストのインデックスにまだコライダーを割り当てていない場合は、空のエントリーの右側にある小さい + ボタンを使って、新しいコライダーを作成して割り当てることができます。この例では、パーティクルシステムの子として新しいゲームオブジェクトを作成し、そこにスフィアコライダーをアタッチしてから、コライダーを空のエントリーに割り当てます。

コライダーを追加した後、特定のトリガーイベントタイプを渡す基準を満たすと、パーティクルの動作を指定することができます。以下のような 4 つのイベントタイプがあり、パーティクルがどのようにコライダーと相互作用するかを表します。

  • Inside: パーティクルがコライダーの境界内にあります。
  • Outside: パーティクルがコライダーの境界の外にあります。
  • Enter: パーティクルはコライダーの境界に入ります。
  • Exit: パーティクルはコライダーの境界を出ます。

Inspector では、これらのイベントタイプごとにドロップダウンがあり、トリガーイベントの条件を満たす場合にパーティクルに何が起こるかを選択することができます。選択肢は次のとおりです。

  • Callback: OnParticleTrigger() コールバック関数でパーティクルにアクセスできるようになります。
  • Kill: パーティクルを破壊します。OnParticleTrigger() コールバック関数でパーティクルにアクセスすることはできません。
  • Ignore: パーティクルを無視します。OnParticleTrigger() コールバック関数でパーティクルにアクセスすることはできません。

OnParticleTrigger() 内でのパーティクルへのアクセス

トリガーイベントの 1 つに対するリアクションとして Callback を選択する場合、アタッチしたスクリプトからイベント条件を満たすパーティクルにアクセスできます。これを行うには、まず OnParticleTrigger() 関数をアタッチしたスクリプトに加える必要があります。この関数内で、ParticlePhysicsExtensions.GetTriggerParticles() 関数を呼び出して、トリガーイベントの条件を満たすパーティクルのリストを取得します。この関数は、パーティクルを取得したいトリガーイベントを指定するParticleSystemTriggerEventType (InsideOutsideEnterExit) と、この関数が結果を表す Particles のリストを受け取ります。このリストから、任意のパーティクルにアクセスしたり、変更したり、破棄したりすることができます。また、この関数は任意のパラメーターをとり、各パーティクルがどのコライダーをトリガーしたかなどの衝突情報を出力することができます。Collider Query Mode プロパティは、このパラメーターを通して利用できる情報を制御します。

API の詳細や使用方法については、以下の例 を参照してください。

プロパティ

プロパティ 説明 
Inside コライダー内のフレームごとに、パーティクルシステムがパーティクルに対して行うアクションを指定します。オプションは以下の通りです。
Callback: パーティクルを OnParticleTrigger() コールバックで取得できるリストに追加します。
Kill: パーティクルを破棄します。
Ignore: パーティクルを無視します。
Outside コライダー外のフレームごとに、パーティクルシステムがパーティクルに対して行うアクションを指定します。オプションは以下の通りです。
Callback: パーティクルを OnParticleTrigger() コールバックで取得できるリストに追加します。
Kill: パーティクルを破棄します。
Ignore: パーティクルを無視します。
Enter コライダーに入るフレームのパーティクルに対して、パーティクルシステムが行うアクションを指定します。オプションは以下の通りです。
Callback: パーティクルを OnParticleTrigger() コールバックで取得できるリストに追加します。
Kill: パーティクルを破棄します。
Ignore: パーティクルを無視します。
Exit コライダーから外に出るフレームのパーティクルに対して、パーティクルシステムが行うアクションを指定します。オプションは以下の通りです。
Callback: パーティクルを OnParticleTrigger() コールバックで取得できるリストに追加します。
Kill: パーティクルを破棄します。
Ignore: パーティクルを無視します。
Collider Query Mode パーティクルが相互作用するコライダーに関する情報を得るために、このパーティクルシステムが使用する方法を指定します。これは Triggers モジュールを処理する際のリソース強度を増加させるので、余分な衝突情報が必要ない場合は、このプロパティを Disabled (無効) に設定してください。オプションは以下の通りです。
Disabled: 各パーティクルがどのコライダーと相互作用するかについての情報を取得しません。
One: 各パーティクルが相互作用する最初のコライダーについての情報を取得します。パーティクルがフレーム内の複数の コライダーと相互作用した場合、Collider リストのパーティクルが相互作用した最初のコライダーを返します。
All: 各パーティクルが相互作用したすべてのコライダーの情報を取得します。
Radius Scale パーティクルのコライダー境界。これにより、パーティクルのコライダー境界をパーティクルの視覚的な外観により近づけることができます。これは、パーティクルが円形でテクスチャでフェードする場合、デフォルトのパーティクルコライダーではパーティクルが目に見える前にトリガーの内側に入ってしまうので便利です。

1 を入力すると、パーティクルコライダーのサイズを同じに保ち、パーティクルがコライダーに触れるとイベントが発生するように見えます。
1 より小さい値を入力すると、パーティクルのコライダーが小さくなり、パーティクルがコライダーを突き通った後にトリガーが発生するように見えます。
1 より大きい値を入力すると、パーティクルのコライダーが大きくなり、パーティクルがコライダーを突き通る前にトリガーが発生するように見えます。
Visualize Bounds シーンビューで各パーティクルのコライダー境界を表示するかどうかを示します。コライダー境界を表示するにはこのプロパティを有効にし、隠すには無効にします。

コライダーとの相互作用

以下の例では、パーティクルがコライダーに侵入すると赤くなり、コライダーの境界から出ると緑に変わります。

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

[ExecuteInEditMode]
public class TriggerScript : MonoBehaviour
{
    ParticleSystem ps;

    // これらのリストは、各フレームでトリガーの条件に
    // 一致するパーティクルを格納します
    List<ParticleSystem.Particle> enter = new List<ParticleSystem.Particle>();
    List<ParticleSystem.Particle> exit = new List<ParticleSystem.Particle>();

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

    void OnParticleTrigger()
    {
        // このフレームのトリガーの条件に一致するパーティクルを取得します
        int numEnter = ps.GetTriggerParticles(ParticleSystemTriggerEventType.Enter, enter);
        int numExit = ps.GetTriggerParticles(ParticleSystemTriggerEventType.Exit, exit);

        // トリガーに侵入したパーティクルを走査し、赤にします
        for (int i = 0; i < numEnter; i++)
        {
            ParticleSystem.Particle p = enter[i];
            p.startColor = new Color32(255, 0, 0, 255);
            enter[i] = p;
        }

        // トリガーから出ていくパーティクルを走査し、緑にします
        for (int i = 0; i < numExit; i++)
        {
            ParticleSystem.Particle p = exit[i];
            p.startColor = new Color32(0, 255, 0, 255);
            exit[i] = p;
        }

        // 変更したパーティクルをパーティクルシステムに再割り当てします
        ps.SetTriggerParticles(ParticleSystemTriggerEventType.Enter, enter);
        ps.SetTriggerParticles(ParticleSystemTriggerEventType.Exit, exit);
    }
}

この例の結果は下の画像の通りです。

エディタービュー
エディタービュー
ゲームビュー
ゲームビュー

複数のコライダーとの相互作用

次の例では、GetTriggerParticles() 関数から抽出できる追加の衝突データを利用しています。1 つ目のコライダーの境界内にあるパーティクルは赤に、2 つ目のコライダーの境界内にあるパーティクルは青に、そして両方のコライダーの境界内にあるパーティクルは緑になります。また、パーティクルがコライダーの内側にない場合は白色になります。この例では、 Collider Query ModeAll に設定しています。

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

[ExecuteInEditMode]
public class TriggerScript : MonoBehaviour
{
    void OnParticleTrigger()
    {
        ParticleSystem ps = GetComponent();
 
        // パーティクル
        List inside = new List();
        List exit = new List();
 
        // get
        int numInside = ps.GetTriggerParticles(ParticleSystemTriggerEventType.Inside, inside, out var insideData);
        int numExit = ps.GetTriggerParticles(ParticleSystemTriggerEventType.Exit, exit);
 
        // 繰り返し
        for (int i = 0; i < numInside; i++)
        {
            ParticleSystem.Particle p = inside[i];
            if (insideData.GetColliderCount(i) == 1)
            {
                if (insideData.GetCollider(i, 0) == ps.trigger.GetCollider(0))
                    p.startColor = new Color32(255, 0, 0, 255);
                else
                    p.startColor = new Color32(0, 0, 255, 255);
            }
            else if (insideData.GetColliderCount(i) == 2)
            {
                p.startColor = new Color32(0, 255, 0, 255);
            }
            inside[i] = p;
        }
        for (int i = 0; i < numExit; i++)
        {
            ParticleSystem.Particle p = exit[i];
            p.startColor = new Color32(1, 1, 1, 255);
            exit[i] = p;
        }
 
        // set
        ps.SetTriggerParticles(ParticleSystemTriggerEventType.Inside, inside);
        ps.SetTriggerParticles(ParticleSystemTriggerEventType.Exit, exit);
    }
}

この例の結果は下の画像の通りです。

Collision モジュール
Sub Emitters モジュール