【Unity】一つのVFXで任意の複数の位置からパーティクルをだす

投稿者: | 2023-03-29

一つのVisual Effectゲームオブジェクトを使って、任意の複数の位置からパーティクルを出したいとき、VFXEventAttribute等を使って位置を設定し、1フレームのうちに複数回VisualEffect.Playメソッドを使うと、最後に設定した位置で一度だけエフェクトが再生されます。

using UnityEngine;
using UnityEngine.VFX;

public class TestVFX : MonoBehaviour
{

    [SerializeField] Transform[] points;
    VisualEffect vfx;

    // Start is called before the first frame update
    void Start()
    {
        vfx = GetComponent<VisualEffect>();
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            VFXEventAttribute attr = vfx.CreateVFXEventAttribute();

            for(int i = 0; i < points.Length; i++)
            {
                attr.SetVector3("position", points[i].position);
                vfx.Play(attr);
            }
        }
    }
}

これは、VFXグラフでは、イベントをフレームの最後まで遅延させて最後のものだけを実行するからだそうです。

Visual Effectゲームオブジェクトを複数作ることもできますが、数が多いとかなり負荷がかかります。

パーティクルIDを使う

particleID属性を使うとこれを簡単に行なえます。パーティクルIDは各パーティクルを識別する整数値です。これを使うと各パーティクルを順番に何かに格納することができます。

例えば、20個のバケットにパーティクルを順番に格納したいときは、パーティクルIDを20で割った余りが0なら1番目、1なら2番目という風に繰り返します。

particleID属性は「Get Attribute: particleId」ノードから返されます。

「Modulo」ノードで、それをパーティクルの数で割った余りを求め、「Set Position」ブロックのXに入力します。

すると、パーティクルが1列に並んで出現します。

テクスチャに位置を格納する

これを使って、任意の複数の位置から一度にパーティクルを発生させてみます。まず、シーンに複数の空のゲームオブジェクトをおいて、スクリプトでその位置を、新しいテクスチャに色として格納します。

using UnityEngine;
using UnityEngine.VFX;

public class TestVFX : MonoBehaviour
{

    [SerializeField] Transform[] points;
    VisualEffect vfx;

    // Start is called before the first frame update
    void Start()
    {
        vfx = GetComponent<VisualEffect>();
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            // 新しいテクスチャを作る
            var texture = new Texture2D(points.Length, 1, TextureFormat.RGBAFloat, false);
            
            // 各位置の処理
            for (int i = 0; i < points.Length; i++)
            {
                var pos = points[i].position;

                // 位置を色にして、座標(i, 0)のピクセルに設定
                texture.SetPixel(i, 0, new Color(pos.x, pos.y, pos.z));
             
            }

            // テクスチャを適用する
            texture.Apply();

            // テクスチャとパーティクル数をVisual Effectに設定
            vfx.SetTexture("Positions", texture);
            vfx.SetInt("Count", points.Length);

            // エフェクトを再生
            vfx.Play();
        }
    }
}

テクスチャを適用したら、それをVisual Effectゲームオブジェクトに設定して、エフェクトを再生しています。

VFXグラフ

VFXグラフでは、パーティクルIDをパーティクルの数で割って、テクスチャからその座標のテクセル値を読み込み、「Set Position」ブロックに入力しています。

「Set Position」ブロックはワールド空間に設定します。

これで任意の複数の位置から一度にパーティクルが出るようになりました。

参考:
https://forum.unity.com/threads/how-do-i-use-vfx-to-spawn-at-multiple-locations-in-one-frame.1303131/ https://forum.unity.com/threads/multiple-event-burst-spawns-of-the-same-vfxgraph-possible.852049/ https://forum.unity.com/threads/what-exactly-is-the-particle-id-operator-and-what-can-you-do-with-it.692503/

コメントを残す

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