MRが楽しい

MRやVRについて学習したことを書き残す

Unityでガベージコレクションの有効無効を切り替える

本日はUnityの小ネタ枠です。
Unityでガベージコレクションの有効無効を切り替える方法です。

ガベージコレクションとは

ガベージコレクションは使用されなくなったメモリ領域を自動的に解放するメモリ管理機能です。
C#では.NET Frameworkが提供するGCが動作しており、開発者が明示的にメモリを解放する必要がありません。
一方でGCが実行されるタイミングで一時的に処理が停止するため、フレームドロップの原因となる可能性があります。

UnityでのGC制御

GarbageCollector

Unity 2018.3以降では GarbageCollector クラスが導入され、Unity独自のGC制御が可能になりました。
GarbageCollectorクラスを使うことで、MonoやIL2CPP環境でGCの有効・無効を切り替えることができます。
docs.unity3d.com

GCを一時的に停止することで、リアルタイム性が求められる処理中にGCによるフレーム落ちを防ぐことができます。
ただし、GCを無効化している間は不要なメモリが解放されないため、メモリ使用量が増加する点に注意が必要です。

// GCを無効化
GarbageCollector.GCMode = GarbageCollector.Mode.Disabled;

// GCを有効化
GarbageCollector.GCMode = GarbageCollector.Mode.Enabled;

Incremental GC

Unity 2019.1.0以降では、更にIncremental GC(インクリメンタルガベージコレクション)の仕組みが導入されました。

Incremental GCは従来のガベージコレクション処理を複数フレームに分割して少しずつ実行することで、1フレームあたりのGC負荷を軽減します。
これにより、GCによる一時的なフレームレート低下(ラグ)が発生しにくくなり、リアルタイム性が求められるゲームやアプリケーションでより安定したパフォーマンスが得られます。

Incremental GCは以下の手順で設定可能です。
メニューから[Edit -> Project Settings]を開き、[Player]タブを開きます。

[Other Settings -> Configuration -> Use Incremental GC]にチェックを入れることで有効になります。

また、Incremental GCは GarbageCollector クラスを通じて制御できます。

// Incremental GCが有効かどうか
bool isIncremental = GarbageCollector.isIncremental;

// Incremental GCの目標時間(ナノ秒)
ulong incrementalTime = GarbageCollector.incrementalTimeSliceNanoseconds;

// Incremental GCを指定時間(ナノ秒)だけ実行する
// 返り値は実行すべきガベージコレクション作業があるかどうか
bool isCollectIn = GarbageCollector.CollectIncremental(1000);

docs.unity3d.com
docs.unity3d.com

なお、WebGLプラットフォームはIncremental GCをサポートしていません。
環境によっては利用できない点に注意が必要です。
docs.unity3d.com