はじめに
今回はGarbageCollectorクラスを用いてガベージコレクションのオン・オフなどを制御してみようという記事になります。
docs.unity3d.com
ガベージコレクションを発生させないようにする
GarbageCollecor.GCModeを変更することによってガベージコレクションを発生させる・させない・手動で行うを選ぶことができます。
ただしWebGLとエディタ上ではサポートされていないことに注意してください。
// エディタ上で実行しようとすると以下のエラーが出る
InvalidOperationException: Setting garbage collector mode is not supported in the editor
public class Test : MonoBehaviour { private void Start() { // ガベージコレクションを発生させないようにする GarbageCollector.GCMode = GarbageCollector.Mode.Disabled; // ガベージコレクションを発生させるようにする // GarbageCollector.GCMode = GarbageCollector.Mode.Enabled; } private void Update() { // Managed Heapに毎フレーム、メモリを確保する var array = new int[100]; } }
GarbageCollector.Mode.Disabledを設定すると、System.GC.Collect()を実行してもGCは働きません。
一応Standalone Macで計測してみた結果、メモリ使用量がどんどん増えていってはいました。

GCModeの変更された時に処理を挟む
GarbageCollector.GCModeChangedを用いることで、GarbageCollector.GCModeが変更された際に処理を挟めます。
GarbageCollector.GCModeChanged += mode => Debug.Log(mode);
インクリメンタルガベージコレクションが有効かどうか調べる
// Incremental garbage collectionが有効化どうか bool isIncremental = GarbageCollector.isIncremental;
GarbageCollector.isIncrementalはPlayer Settingsで有効になっている かつ プラットフォームがサポートされている場合にtrueになります。
またインクリメンタルガベージコレクションが何者かについては、Unity公式ドキュメントに記載があります。
インクリメンタル ガベージコレクション (GC) は、ガベージコレクションの処理を複数のフレームに分散して行います。これは、Unity のデフォルトのガベージコレクションの動作です。
...
インクリメンタルモードでは、ガベージコレクションが全体的に速くなるわけではありませんが、ワークロードを複数のフレームに分散させるため、GC 関連のパフォーマンススパイクが減少します。このような中断は GC スパイク と呼ばれます。これは、Profiler ウィンドウ のフレームタイムグラフに大きなスパイクとして表示されるためです。
インクリメンタルガベージコレクションを手動実行する
// Incremental garbage collectionを手動実行する // 返り値は追加のガベージコレクション作業が残っているかどうか GarbageCollector.CollectIncremental(nanoseconds: 0UL);
ただしIncremental Garbage Collectionが有効でないと動作しません。(返り値は常にfalse)
インクリメンタルガベージコレクションの1Stepに制限時間を設ける
GarbageCollector.incrementalTimeSliceNanosecondsに時間を指定することで、インクリメンタルガベージコレクションの1ステップでの制限時間を指定できるそうです。
The target duration of a collection step when performing incremental garbage collection.
Scripting.GarbageCollector-incrementalTimeSliceNanoseconds - Unity スクリプトリファレンス