UnityC#を高速化する方法を自分用にメモすることにしました。
[ 対処法 ]
GameObject.Find()の使用を避ける
GameObject.Find()は重たい処理なので高頻度で呼ばれる関数(Update系関数など)で呼ぶのは避けた方が良いです。オブジェクトを取得したい場合はStart関数で取得してキャッシュしておきましょう。
GetComponentの使用を避ける
GetComponentは重たい処理なので高頻度で呼ばれる関数(Update系関数など)で呼ぶのは避けた方が良いです。コンポーネントを取得したい場合はStart関数で取得してキャッシュしておきましょう。
transformの読み書きを避ける
transformの読み書きは重たい処理なので避けた方が良いです。
Instantiate()の使用を避ける
Instantiate()は重たい処理なので呼ぶのは避けた方が良いです。何度も同じオブジェクトを生成する必要がある時はオブジェクトプールを実装することでInstantiate()の使用頻度を減らすことができます。
Destroy()の使用を避ける
Destroy()は重たい処理なので呼ぶのは避けた方が良いです。
GCが重たくなる処理を避ける
GCとは、コンピューターが自動的にメモリを確保したり、確保したメモリの中から必要なくなったメモリ領域を自動的に解放したりする機能だそうです。新たにメモリ領域を確保しようとするとGCは発動するようで、発動すると重くなりFPSが急激に低下します。
edunity.hatenablog.com
edunity.hatenablog.com
HashSetを使う
要素の検索速度はListよりHashSetの方が圧倒的に速いので、高頻度で要素検索をする場合はArrayやListの代わりにHashListを使った方が良いです。ただしHashSetは重複要素を持つこととindexを使った要素指定ができません。
edunity.hatenablog.com
edunity.hatenablog.com
sqrMagnitudeを使う
以下は座標Aから座標Bまでの距離と座標Aから座標Cまでの距離が等しいか否かを変数tmpに格納するプログラムです。後者の方が処理速度が速いです。これはsqrMagnitudeを使うと処理に時間がかかるルート計算を避けれるからです。
bool tmp = Vector3.Distance(PosB, PosA) == Vector3.Distance(PosC, PosA);
bool tmp = (PosB - PosA).sqrMagnitude == (PosC - PosA).sqrMagnitude;
MaterialPropertyBlock()を使う
処理結果が同じになる2種類の処理がありますが後者の方が処理速度が速いです。
private void Start() { GetComponent<Renderer>().material.SetColor("_Color", Color.red); }
private readonly int _Color = Shader.PropertyToID("_Color"); private void Start() { MaterialPropertyBlock MaterialPropertyBlock = new MaterialPropertyBlock(); MaterialPropertyBlock.SetColor(_Color, Color.red); GetComponent<Renderer>().SetPropertyBlock(MaterialPropertyBlock); }
StringToHash()を使う
処理結果が同じになる2種類の処理がありますが後者の方が処理速度が速いです。
private void Start() { GetComponent<Animator>().SetFloat("Speed", 1.0f); }
private readonly int Speed = Animator.StringToHash("Speed"); private void Start() { GetComponent<Animator>().SetFloat(Speed, 1.0f); }
ToString()を使う
処理結果が同じになる2種類の処理がありますが後者の方が処理速度が速いです。これはボクシングを避けれるからです。
string tmp = "ABC" + 123;
string tmp = "ABC" + 123.ToString();
CompareTag()を使う
処理結果が同じになる2種類の処理がありますが後者の方が処理速度が速いです。
bool tmp = gameObject.tag == "b";
bool tmp = gameObject.CompareTag("b");
累乗計算の記述方法に気を付ける
処理結果が同じになる2種類の処理がありますが後者の方が処理速度が速いです。
float tmp = Mathf.Pow(5, 3);
float tmp = 5 * 5 * 5;
Linqの記述方法に気を付ける
処理結果が同じになる2種類の処理がありますが後者の方が処理速度が速いです。
List<int> List = new List<int>(){1, 2, 3, 4, 5}; if(List.Count(Item => Item >= 0) > 0) { }
List<int> List = new List<int>(){1, 2, 3, 4, 5}; if(List.Any(Item => Item >= 0)) { }
配列へのアクセス順序に気を付ける
処理結果が同じになる2種類の処理がありますが後者の方が処理速度が速いです。この速度差にはキャッシュへのアクセス速度とメモリへのアクセス速度の差が関係しています。
for(i = 0; i < 100; i++) { for(j = 0; j < 100; j++) { Ary2[j][i] = Ary1[j][i]; } }
for(j = 0; j < 100; j++) { for(i = 0; i < 100; i++) { Ary2[j][i] = Ary1[j][i]; } }
計算回数を減らす
処理結果が同じになる2種類の処理がありますが後者の方が処理速度が速いです。これは前者より後者の方が比較回数が少ないからです。
for(int i = 0; i < 100; i++) { if(a == true) { Ary[i] = i; } else { Ary[i] = -i; } }
if(a == true) { for(int i = 0; i < 100; i++) { Ary[i] = i; } } else { for(int i = 0; i < 100; i++) { Ary[i] = -i; } }
定数はconstを使って定義する
定数は変数として定義するよりも定数として定義した方がプログラムの実行効率が上昇します。
private const int tmp = 0;