OnDestroyの処理中にInstantateは避けるべき
先日のゲームジャムで、ゲームのシーンを終了させた時に大量のパーティクルがシーンに残るといった事案が発生しました。何が原因かと調べてみた所、パーティクル生成をOnDestroyで行っていることが原因でした。
OnDestroyはオブジェクトが消滅したタイミングで呼ばれる命令ですが、
これの実行中にInstantiateを呼ぶとシーン再生終了時にゴミが残る事象があります。
これは例えば、こんなコードで発生します。
void OnDestroy ()
{
GameObject.Instantiate (new GameObject ("gomi"));
}
この現象が発生した祭、下のようなメッセージが表示されるので、
分かりやすいです。
Some objects were not cleaned up when closing the scene. (Did you spawn new GameObjects from OnDestroy?)
さて、この事象のそもそもの原因ですが、Unityのシーンの再生停止処理にキモがあります。
Unityはシーン再生を停止する時、シーンの状態を再生前に戻します。
これは挙動を確認する限り、シーンのオブジェクトを全て破棄し
シーン再生時の状態をロードしてるみたいです。
その為、OnDestroyにInstantate処理を記述しておくと、
破棄フェイズでゴミを生成してしまう…といった訳です。
これを回避するには、OnApplicationQuitで終了判定を取得しておき、
終了していた場合は生成しない…といった回避が必要みたいです。
private static bool isQuitting = false;void OnApplicationQuit ()
{
isQuitting = true;
}void OnDestroy ()
{
if (!isQuitting)
GameObject.Instantiate (new GameObject ("gomi"));
}
他の方法も探しましたが、残念ながら見つけることは出来ませんでした。
正直面倒なので、
削除する際に何かパーティクルとか生成しない方が良さそうです。