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;
StringBuilderveya TextMeshPro'nunSetTextmetodunu kullanın. - Koleksiyonlar: Listeleri alan olarak tutup
Clear()ile yeniden kullanın. - Physics:
RaycastNonAlloc,OverlapSphereNonAllocgibi 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'ı
objectolarak geçmek, enum'u Dictionary key yapmak (eski runtime'larda) allocation yaratır. - Instantiate/Destroy: Object pooling kullanın.
- `GetComponent` / `gameObject.tag`:
tagstring döndürür;CompareTagkullanı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.
İlgili Unity & C# soruları
- Unity'de Update, FixedUpdate ve LateUpdate arasındaki fark nedir?
- GetComponent çağrılarını neden önbelleğe almalısınız?
- Rigidbody, physics layer'lar ve raycast nasıl çalışır? FixedUpdate neden önemlidir?
- C# delegate, event ve UnityEvent arasındaki farklar nelerdir?
- C#'ta struct ile class arasındaki fark nedir? Value type ve reference type oyunda neden önemlidir?
- Prefab nedir? Prefab variant ve nested prefab ne işe yarar?
Bu konuda başka bir soru biliyor musun?
Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.