Unity Term Book
グラフィックスとエフェクト

VFX & Particle System

Unity には二つの粒子系があります——柔軟な CPU ベース Particle System と、GPU で数百万粒を扱える VFX Graph。炎・煙・雨・魔法 FX の選び方と、Play・Emit・SendEvent の制御を学べます。図解とシミュレーターで粒子パラメータを試し、自学にも使えます。

想像してみてください...

Particle System手で打ち上げる花火——発射レート、角度、色を設定し、CPU が各粒子を更新します。 精密ですが数が増えると遅い。VFX Graph産業用花火マシン——すべて GPU で並列なので 数百万粒が可能ですが、強力な GPU と URP/HDRP が必要。粒子数、対象プラットフォーム、挙動の複雑さで選びます。

概念の詳細

Particle System(別名 Shuriken)は GameObject 上のコンポーネントで、 CPU 上で粒子を生成・更新します。各粒子は位置、速度、色、サイズ、寿命を持ちます。モジュール (Emission、Shape、Velocity、Color over Lifetime、Force、Collision…)で細かく制御。向き:小さな炎、雨、雪、ヒット FX、煙——数十〜数千粒。

VFX Graph(Visual Effect Graph)はすべて GPU コンピュートシェーダーで動きます。 Shader Graph に似たノードグラフで更新ロジックを組み立てます(Initialize、Update、Output)。 良い性能で数百万粒。要件:URP または HDRP、Compute Shader 対応 GPU(2015+ の大半)、古い Android/iOS は非対応。

VFX Graph は粒子を分けます:Spawn(rate/burst)、 Initialize(初期属性)、Update(毎フレームの物理・色・サイズ)、 Output(描画方法:quad、mesh、ribbon)。コンテキストはデータフローでつながり、レンダーパイプラインのようです。

性能:Particle System はライブ粒子がおおよそ 1000 未満ならモバイル/コンソールでも問題ありません。 maxParticles で上限し、再生後は Stop Action = DisableVFX Graph の方がスケールしますが、対象プラットフォームでプロファイリングしてください。

Particle System と VFX Graph

比較項目Particle SystemVFX Graph
処理CPUGPU (Compute Shader)
最適な粒子数100 – 10,00010,000 – 10,000,000+
PipelineBuilt-in, URP, HDRPURP, HDRP only
Mobile✅ 良好⚠️ 制限あり
InterfaceInspector moduleNode graph editor
Script API完全な C# APILimited (SetFloat, SetTexture)
使うとき炎、雨、ヒット FX、煙銀河、流体、群衆、破壊

ハンズオン手順(Particle System)

1

Particle System を作成

GameObject → Effects → Particle System、または既存 GameObject に Add Component → Particle System。

2

Main モジュールを設定

Duration、Looping、Start Lifetime、Start Speed、Start Size、Start Color — 基本項目。

3

放出形状を選ぶ

Shape モジュール:Cone(炎)、Sphere(爆発)、Box(上からの雨)、Circle(リング)。Radius と Arc を調整。

4

Color over Lifetime を有効化

グラデーションを追加:赤 → オレンジ → 黄 → 透明で炎をフェードアウト。

5

必要時にコードから再生

ps.Play() / ps.Stop() / ps.Emit(count) — または EmitParams で瞬間バースト。

インタラクティブシミュレーター

Particle System パラメータを調整し、Burst / プリセットで効果を確認。

生存パーティクル:0Mode: Fire

コード例

基本

Particle System の Play/Stop と、必要時のバースト Emit(例:ヒット効果)。

using UnityEngine;

public class HitEffect : MonoBehaviour
{
  public ParticleSystem sparks;
  public ParticleSystem smoke;

  // Call on bullet impact — PlayOneShot a prefab at a position
  public static void PlayAt(Vector3 pos, Vector3 normal,
                             GameObject fxPrefab)
  {
      GameObject fx = Instantiate(fxPrefab, pos,
          Quaternion.LookRotation(normal));
      Destroy(fx, 2f); // Clean up after 2 seconds
  }

  // Burst emit: 30 particles immediately, no looping
  public void BurstEmit()
  {
      ParticleSystem.EmitParams ep = new ParticleSystem.EmitParams();
      ep.position = transform.position;
      sparks.Emit(ep, 30);
      smoke.Play();
  }

  // Change particle color at runtime via Main module
  public void SetColor(Color color)
  {
      var main = sparks.main;
      main.startColor = new ParticleSystem.MinMaxGradient(color);
  }
}

コード例

上級

C# から VFX Graph を駆動——ExposedProperty でプロパティ設定とイベント発火。

using UnityEngine;
using UnityEngine.VFX;

public class VFXController : MonoBehaviour
{
  public VisualEffect vfx;

  // Property IDs — must match Exposed Property names in VFX Graph
  static readonly int SpawnRateID = Shader.PropertyToID("SpawnRate");
  static readonly int ColorID     = Shader.PropertyToID("BaseColor");
  static readonly int ExplodeID   = Shader.PropertyToID("OnExplode");

  void Start()
  {
      vfx.SetFloat(SpawnRateID, 50f);
      vfx.SetVector4(ColorID, new Vector4(1f, 0.5f, 0f, 1f));
  }

  public void Explode()
  {
      // SendEvent fires an event in VFX Graph (Burst spawn)
      vfx.SendEvent(ExplodeID);
  }

  public void SetIntensity(float t)
  {
      // Spawn rate 0 → 500 from intensity
      vfx.SetFloat(SpawnRateID, Mathf.Lerp(0f, 500f, t));
  }
}

📌 要点

  • Particle System: CPU、全プラットフォーム、<10k 粒子
  • VFX Graph: GPU、URP/HDRP のみ、数百万粒
  • Stop Action = Disable で再利用(オブジェクトプーリング)
  • ps.main.startColor は struct として再代入が必要
  • VFX Graph: SendEvent() が Burst コンテキストを発火

⚠️ よくあるミス

  • ❌ Destroy なしで多数の PS プレハブをスポーン

    何千もの Particle System が積み上がり重いラグ

    ✅ PS をプールするか、終了後 Destroy(fx, lifetime)

  • ❌ ps.main.startColor.color を直接編集

    struct コピー——変更が反映されない

    ✅ var main = ps.main; main.startColor = new MinMaxGradient(c);