UnityのParticleSystemにはパーティクルのシミュレーション時間を任意の時間で制御することのできるParticleSystem.Simulateが用意されています。しかし、ParticleSystem.Simulateに大きな秒数を指定するとシミュレーションを開始した際に大きなスパイクが発生してしまうケースがあります。本記事では、その具体的な事例と注意点について紹介します。
ParticleSystem.Simulateについての公式ドキュメント*1 ParticleSystem.Simulateを使用すると第1引数で指定した時間までパーティクルの演出をシミュレーションし、指定した時間からパーティクルを再度再生することが可能です。
リスト4.1: 0秒時点から再生し直す
1 | ParticleSystem.Simulate(0f, false, true); |
リスト4.1のように0秒を指定すると途中まで再生していたパーティクルを最初から再生し直す仕組みを作れます。
リスト4.2: 5秒時点から再生し直す
1 | ParticleSystem.Simulate(5f, false, true); |
リスト4.2のように5秒を指定すると再生中のパーティクルを5秒時点から再生し直す仕組みを作れます。
図4.1: 問題のあるパーティクル
Unityのデフォルトで作成できるパーティクルに追加でNoiseモジュールをオンにします。他に調整しているパラメータはパーティクルを見やすくするためにEmissionモジュールで一直線になるように発生を調整しています。
リスト4.3: 20秒時点から再生し直す
1 | ParticleSystem.Simulate(20f, false, false); |
そしてこのようなNoiseモジュールを使用したパーティクルをリスト4.3のように第1引数の秒数指定に大きすぎる秒数を入れてシミュレーションしてしまうと処理中に大きなスパイクが発生します。
リスト4.4: シミュレーションの負荷計測
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | void OnClickA() { // 再生中のパーティクルがあれば破棄 if (_activeParticle != null) { Destroy(_activeParticle); _activeParticle = null; } // 新規生成して再生 _activeParticle = Instantiate(particlePrefab, Vector3.zero, Quaternion.identity); var ps = _activeParticle.GetComponent<ParticleSystem>(); if (ps != null) { ps.Play(); } } void OnClickB() { if (_activeParticle == null) return; var ps = _activeParticle.GetComponent<ParticleSystem>(); if (ps != null) { Profiler.BeginSample("再シミュレーション"); // 再シミュレーション ps.Simulate(20f, false, false); Profiler.EndSample(); ps.Play(); } } |
どれほどの負荷がかかるのか、Profilerで確認します。ButtonAで作成したパーティクルを生成、ButtonBでパーティクルをシミュレートするコードです。UnityのProfilerで確認した時にParticleSystem.Simulateに問題があるのか調べやすくするためにProfiler.BeginSample、Profiler.EndSampleで囲い、調査しやすくします。
図4.2: スパイクが発生している様子
図4.3: 処理時間
このようにParticleSystem.Simulate時、ParticleSystemのNoiseモジュールでNoiseJobが約2000回コールされ、これにより約50msのスパイクが発生しています。このコール数はParticleSystemのMax Particlesを下げることで少しは減らすことが可能です。
ParticleSystem.Simulateを使用して任意の秒数からパーティクルを発生させる仕組みを作る必要がある場合、
を確認し、特にNoiseモジュールを有効にしているパーティクルを使用する場合はParticleSystem.Simulateの利用を控えた方が良いです。