はじめに
UnityのパーティクルシステムにあるParticleSystem.Simulate、これの第1引数に時間を入れることでパーティクルをその時間まで進めて再開する仕組みを作ったりができます。
しかし、ParticleSystem.Simulateの時間に長すぎる時間を入れると大きなスパイクが発生してしまう問題に気が付いたのでメモとして残します。
ソースコード
検証で使用したソースコードです。
ParticleSystem.Simulateとは?
Simulateを使うと第1引数で指定した時間までパーティクルの演出をシミュレーションして、その時間からパーティクルを再生することができます。
ParticleSystem.Simulate(0f, false, true);
のようにすることで途中まで再生していたパーティクルをやり直したり、
ParticleSystem.Simulate(5.0f, false, true);
5.0秒からやり直す、といったことができるようになります。
問題がある使い方
ParticleSystem.Simulate(20.0f, false, false);
のように、第1引数に大きすぎる値を入れると、処理中に大きなスパイクが発生します。
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();
}
}
ButtonAでパーティクルを生成、ButtonBでパーティクルをSimulateするテストコードです。
このようなコードを処理したときのProfiler.BeginSample("再シミュレーション")の処理をProfilerで確認してみると、
今回生成しているパーティクルではNoiseモジュールを使用しているのですが、それが約2000回のコール、これによって50msほど時間がかかってしまっています。
おそらく、20秒分のパーティクルの動きを1fでSimulateした結果これだけコールが増えてしまい、1fで処理しきれずに時間がかかってしまっているのだと思います。
そのため、第1引数に入れる数値には注意が必要です。

