「毎日Unity」の技術ブログ

開発で役立つ情報を発信する

【Unity】ProfilerのGC(GarbageCollector)が重い時の解決方法

ProfilerのGC(GarbageCollector)が重い時の解決方法を記事にしました。

[ そもそもGCって何? ]

GCとは、コンピューターが自動的にメモリを確保したり、確保したメモリの中から必要なくなったメモリ領域を自動的に解放したりする機能だそうです。
新たにメモリ領域を確保しようとするとGCは発動するようで、発動すると重くなりFPSが急激に低下します。

[ 解決方法 ]

「メモリ確保」=「GC」=「重くなる」なので、メモリ確保を必要とする処理を避けるか重くなっても良い瞬間にまとめておくことで解決できます。例えばシーン開始時(Start関数とか)にまとめておけば、シーン開始以降にGCで重くなることはなくなりますね。

[ GCが発生してしまう処理 ]

僕が現在覚えている範囲でGCが発生してしまう処理を簡単にまとめました。間違っていたらごめんなさい。

コレクションに要素を追加

コレクションに要素を追加するとGCが発生してしまいます。コレクションを使いたい時はできるだけ配列を使うようにしましょう。
どうしても使わないといけない時は下記のように初期化時にキャパシティを指定しましょう。

//これだめ
List<int> ListTest = new List<int>();

//これいい
List<int> ListTest = new List<int>(123);

Listの初期化

Listを初期化する時は下記のようにnewではなくClear()をすることでGCを避けることができます。

//これだめ
ListTest = new List<int>();

//これいい
ListTest.Clear();

文字列演算

文字列演算するとGCが発生してしまいます。文字列を演算したい時は事前にStringBuilderでメモリ確保をしておきましょう。

空文字列

空文字列を使いたい時は下記のように代わりにstring.Emptyを使ようようにしましょう。

//これだめ
string StringTest = "";

//これいい
string StringTest = string.Empty;

new

newはよくVector3やVector2を使用する時に使いますよね。newを使うとGCが発生してしまうみたいです。

Coroutine

コルーチンを呼び出す時にGCが発生してしまうのでできるだけ使わないようにしましょう。

yield return 0;

「yield return 0;」を使いたい時は下記のように代わりに「yield return null;」を使いましょう。

//これだめ
yield return 0;

//これいい
yield return null;

Instantiate()

これもGCが発生してしまうみたいですね。何度も同じオブジェクトを生成する必要がある時はオブジェクトプールを実装することでInstantiate()の使用頻度を減らすことができます。

Destroy()

これもGCが発生してしまうみたいですね。

LINQ

LINQは便利ですが避けた方が良いみたいです。

ラムダ式

記述の仕方によってはGCが発生するみたいです。

GetComponent

これもGCが発生してしまうみたいですね。

[ 関連記事 ]

edunity.hatenablog.com