Bellek Havuzu (Object Pool): Oyunda Nesneleri Verimli Yönetme
Oyunlarda her saniye yüzlerce nesne oluşturup silmek sistem kaynağını boşa harcar. Mermi ateşlediğinde yeni nesne oluşturmak, mermi hedefe ulaştığında silmek, bu işlem tekrar tekrar yapılırsa, bellek parçalanması ve çöp toplayıcı (garbage collector) gecikmesi ortaya çıkar. Bellek havuzu (object pool) bu sorunu çözer: nesneleri önceden oluşturup depolayan ve gerektiğinde geri döngüsel olarak kullanan bir sistem.
Temel Mantık
Havuzda belirli sayıda nesne önceden hazırlanır. Bir nesneye ihtiyaç duyulduğunda havuzdan alınır ve kullanılır. İş bittiğinde silinmez, havuza geri konur. Bu sayede bellek tahsisi bir kez yapılır, sonrasında yalnızca nesne durumu sıfırlanır.
Adım Adım Uygulama
Birinci adım: havuz sınıfı oluşturmak. Mermi için basit bir havuz yazalım.
1public class BulletPool2{3private Queue<Bullet> availableBullets;4private List<Bullet> allBullets;5private int poolSize = 50;67public BulletPool()8{9availableBullets = new Queue<Bullet>(poolSize);10allBullets = new List<Bullet>(poolSize);1112for (int i = 0; i < poolSize; i++)13{14Bullet bullet = new Bullet();15bullet.SetActive(false);16availableBullets.Enqueue(bullet);17allBullets.Add(bullet);18}19}2021public Bullet GetBullet(Vector3 position, Vector3 direction)22{23Bullet bullet;24if (availableBullets.Count > 0)25{26bullet = availableBullets.Dequeue();27}28else29{30bullet = new Bullet();31allBullets.Add(bullet);32}3334bullet.Reset(position, direction);35bullet.SetActive(true);36return bullet;37}3839public void ReturnBullet(Bullet bullet)40{41bullet.SetActive(false);42availableBullets.Enqueue(bullet);43}44}İkinci adım: mermi sınıfı havuz ile çalışacak şekilde tasarlamak.
1public class Bullet2{3public Vector3 position;4public Vector3 direction;5private bool isActive;67public void Reset(Vector3 pos, Vector3 dir)8{9position = pos;10direction = dir.normalized;11}1213public void SetActive(bool active)14{15isActive = active;16}1718public bool IsActive() => isActive;1920public void Update()21{22if (!isActive) return;23position += direction * 10f * Time.deltaTime;24}25}Üçüncü adım: oyun döngüsünde havuzu kullanmak.
1BulletPool bulletPool = new BulletPool();23void OnShoot(Vector3 pos, Vector3 dir)4{5Bullet bullet = bulletPool.GetBullet(pos, dir);6}78void OnBulletHit(Bullet bullet)9{10bulletPool.ReturnBullet(bullet);11}Çıktı: İlk karede 50 mermi belleğe alınır. Ateş ettikçe havuzdan çekilir, isabet ettikçe geri konur. Bellek tahsisi artmaz, çöp toplayıcı çalışmaz.
Pratik İpucu
Havuz boyutunu oyunun en yoğun anına göre ayarla. Eğer maksimum 100 mermi aynı anda uçabiliyorsa, havuz boyutu en az 100 olmalı. Havuz boşalırsa, yeni nesne oluşturma maliyeti ortaya çıkar; bu da performans düşüşüne neden olur.
5 yorum
dinamik havuz işe yarayabiliyor ama ihtiyaca göre büyüyüp küçülmesi kodlama tarafında daha karışık oluyor
ya ben de düşündüm hep yeni mermi oluşturmak yerine havuzdan almak çok daha mantıklı ne kadar az bellek sızıntısı oluyor fark ettim
aynen o yüzden ben sabit tutuyorum ne kadar nesneler gerekliyse baştan hesapla koy havuzda sonra uğraşma
ama havuzun boyutunu yanlış ayarlarsan boku çıkıyor az havuz açarsan yine bellek patlar çok havuz açarsan boşa yer kaplar
Mermi havuzunda bunu uygulamışım fark inanılmaz Başta yüz mermi oluştursam bile sonra hep aynı nesneleri geri döngüyle kullanıyorsun bellek patlamıyor