Unity'de garbage collection neden frame düşüşüne yol açar? Update içinde allocation'dan nasıl kaçınırsınız?

Cevap

Unity'nin GC'si (Boehm, incremental mod destekli) heap dolduğunda çalışır ve toplama süresince ana thread'i durdurabilir. Her kare küçük allocation'lar yapılırsa GC periyodik olarak tetiklenir ve ani takılmalar (GC spike) oluşur. 60 FPS'te bir karenin bütçesi yalnızca ~16.6 ms'dir.

Sık görülen allocation kaynakları ve çözümleri

// KÖTÜ: her kare allocation
void Update()
{
    scoreText.text = "Skor: " + score;            // string birleştirme
    var enemies = FindObjectsOfType<Enemy>();     // yeni dizi
    var hits = Physics.RaycastAll(ray);           // yeni dizi
    var near = list.Where(e => e.hp > 0).ToList(); // LINQ + closure
}

// İYİ
readonly RaycastHit[] hitBuffer = new RaycastHit[16];
int lastScore = -1;

void Update()
{
    if (score != lastScore) { scoreText.SetText("Skor: {0}", score); lastScore = score; } // TMP, değişince güncelle
    int count = Physics.RaycastNonAlloc(ray, hitBuffer);   // önceden ayrılmış buffer
    for (int i = 0; i < count; i++) { /* ... */ }
}
  • String: Her değişiklikte değil, sadece değer değiştiğinde güncelleyin; StringBuilder veya TextMeshPro'nun SetText metodunu kullanın.
  • Koleksiyonlar: Listeleri alan olarak tutup Clear() ile yeniden kullanın.
  • Physics: RaycastNonAlloc, OverlapSphereNonAlloc gibi NonAlloc sürümleri.
  • LINQ ve lambda: Sıcak yolda (hot path) kullanmayın; dış değişken yakalayan lambda her seferinde closure oluşturur.
  • Boxing: Struct'ı object olarak geçmek, enum'u Dictionary key yapmak (eski runtime'larda) allocation yaratır.
  • Instantiate/Destroy: Object pooling kullanın.
  • `GetComponent` / `gameObject.tag`: tag string döndürür; CompareTag kullanın.
  • yield return new WaitForSeconds(1) her seferinde yeni nesne oluşturur; önbelleğe alın.

Ölçmek

Profiler'da GC.Alloc sütununu ve Deep Profile ile kaynağı bulun. Hedef, oynanış sırasında kare başına 0 B allocation'dır. Ek olarak Player Settings'te Incremental GC açılarak duraklamalar birden fazla kareye yayılabilir.

  1. Unity'de Update, FixedUpdate ve LateUpdate arasındaki fark nedir?KolayUnity & C#Game Dev
  2. GetComponent çağrılarını neden önbelleğe almalısınız?KolayUnity & C#Game Dev
  3. Rigidbody, physics layer'lar ve raycast nasıl çalışır? FixedUpdate neden önemlidir?OrtaUnity & C#Game Dev
  4. C# delegate, event ve UnityEvent arasındaki farklar nelerdir?OrtaUnity & C#Game Dev
  5. C#'ta struct ile class arasındaki fark nedir? Value type ve reference type oyunda neden önemlidir?OrtaUnity & C#Game Dev
  6. Prefab nedir? Prefab variant ve nested prefab ne işe yarar?KolayUnity & C#Game Dev

Bu konuda başka bir soru biliyor musun?

Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.

Soru ekle