Unity’de Performans Optimizasyonu: Daha Akıcı ve Verimli Oyunlar İçin İpuçları

 

Unity ve Performans Optimizasyonu

Herkese merhaba,

Bu yazımda sizlere oyun geliştirme sürecinin ilk aşamalarında ben de dahil olmak üzere çoğu geliştiriciler tarafından zaman zaman göz ardı edilen ancak çok önemli olan performans konusundan bahsedeceğim. Çok önemli dedim çünkü performans oyuncu deneyimini doğrudan etkileyen kritik bir faktör. Oyunculara daha akıcı ve zevkli bir deneyim sunmak ve oyunumuzun daha fazla talep görmesi ve oynanması için yüksek kare hızları (FPS) ve düşük gecikme süreleri gibi detaylara dikkat ederek geliştirme yapmamız gerekiyor. Unity, bu anlamda çok güçlü bir oyun motoru ve doğru kullanıldığında yüksek performanslı oyunlar geliştirmemize oldukça yardımcı oluyor. Bu kadar önemli olduğunu deneyimlediğim için Unity ile performans optimizasyonu için neler yapabiliriz, en etkili teknikler ve ipuçları nelerdir, onları araştırdım. Gelin, başlayalım.

1. Profiler Kullanımı

Unity Profiler, oyunun performansını analiz etmek için kullanılan bir araç. Profiler, CPU ve GPU kullanımını, bellek tahsisini, ve diğer performans metriklerini izliyor. Bu araç sayesinde performans sorunlarının kaynağını tespit edip buna yönelik çözüm üretme şansına sahip oluyoruz.

Nasıl Kullanılır?

  • Öncelikle Profiler’ penceresini açmak için Window => Analysis => Profiler adımlarını kullanıyoruz. Bununla performans verilerini görmeyi amaçlıyoruz.
  • Sonrasında oyunumuzu oynarken Profiler’ı çalıştırıyoruz ve gerçek zamanlı olarak verileri toplamasını bekliyoruz. Farklı sahnelerdeki performansı inceleyerek oyundan bir feedback almış oluyoruz.
  • Bu noktada topladığımız verilerle ilgili analiz yapıyoruz. Bunun için Profiler penceresinde bulunan CPU, GPU, Rendering, Memory gibi farklı sekmeleri inceleyebiliriz ve buradaki performans düşüren noktaları belirleyebiliriz.

2. Grafik Ayarlarını Optimize Etmek

LOD (Level of Detail) Kullanımı

LOD, uzaktaki nesnelerin daha az detaylı modellerle render edilmesini sağlar. Bu, oyundaki nesnelerin bazılarını ayrıntılarından arındırarak özellikle büyük sahnelerde performansı artırır.

  • LOD Grupları Oluşturma: Bir oyunda hangi nesnelerin daha detaylı gösterileceği, hangilerinin tüm detaylarına ihtiyaç duyulmayacağını Unity’e bildirebilmek için farklı detay seviyeleri oluşturabiliriz. Bunu çoğunlukla nesneler için yaparız ve LOD Grubu bileşeni ile yönetiriz Böylelikle özellikle büyük sahnelerde göz önünde olmayan nesneler daha az detaylı modeli ile render edilir ve performans artışı sağlanır.
  • Culling: Kamera görüş alanı dışındaki nesneleri render etmemize gerek olmayacak şekilde bir oyun planı koyarak performans artışı konusunda gelişme sağlayabiliriz. Occlusion Culling kullanarak performansı artırabiliriz.

Batching Teknikleri

  • Static Batching: Statik (hareketsiz) nesneler için kullanılır. Birçok nesneyi tek bir draw call ile render eder.
  • Dynamic Batching: Dinamik (hareketli) nesneler için kullanılır. Küçük ve benzer nesneleri birleştirerek draw call sayısını azaltır.

3. Fizik ve Çarpışma Optimizasyonu

Rigidbody ve Collider Ayarları

  • Gereksiz yere Rigidbody bileşeni eklemek performans düşüşüne sebep olabilir. Bunun yerine sadece fiziksel etkileşime giren nesnelere eklemek yeterlidir.
  • Mümkünse daha basit Collider türlerini kullanmak oyun performansı ile ilgili bir başka nokta. Basit Collider türlerine Box ve Sphere’i örnek verebiliriz. Bu gibi daha standardize edilmişlerin yerine Mesh Collider kullanmak performansı olumsuz etkileyebilir.

Fizik Simülasyonu

  • Fizik simülasyonu oyunu gerçekçi kılmak için önemli. Ancak, fizik hesaplamaları çoğu zaman yoğun kaynak kullanımı gerektiriyor ve bu da oyun performansını etkiliyor. Bunu önlemek için yapabileceğimiz ilk şey Fixed Timestep değerini ayarlamak. Fizik simülasyonu, her çerçevede değil, belirli zaman aralıklarında güncelleniyor. Bu aralık Fixed Timestep olarak adlandırılıyor ve bunu Edit => Project Settings => Time adımlarından ayarlayabiliriz. Bu değer varsayılan olarak 0.02 (50 FPS) olarak ayarlanmıştır. Bu değeri, oyunumuza ve performans gereksinimlerimize göre ayarlayabiliriz. Daha yüksek bir değer daha az fizik güncellemesi anlamına gelir ve bu da performansı artırabilir, ancak fizik simülasyonunun doğruluğunu azaltabilir.
  • Bir diğer konu fizik katmanları (Physics Layers) ile yapılabilecekler. Fizik katmanları, hangi nesnelerin birbirleriyle çarpışacağını kontrol eder. Gereksiz çarpışma kontrollerini önlemek için bu katmanları kullanabiliriz. Önce Edit => Project Settings => Tags and Layers adımlarından yeni katmanlar oluştururuz. Sonrasında nesneleri Inspector panelinden uygun katmanlara atama yaparız. Son olarak Edit => Project Settings => Physics adımlarından hangi katmanların birbirleriyle çarpışacağını belirleriz. Örneğin, oyuncu ve mermi katmanları arasında çarpışma olabilir, ancak arka plan nesneleriyle mermiler arasında çarpışma olmayabilir. Bu durumda gereksiz olan çarpışmanın arka planda çalışmasına gerek yoktur. Ve tabi performansı düşürmesine de.

4. Bellek Yönetimi

Nesne Havuzlama (Object Pooling)

  • Bu yöntem, sıkça oluşturulan ve yok edilen nesneler için önceden belirli sayıda nesne yaratıp bunları yeniden kullanmayı sağlıyor. Özellikle sürekli olarak yeni nesne oluşturma ve yok etme işlemleri performansı olumsuz etkileyebileceğinden, nesne havuzlama ile bu maliyeti azaltabiliyor ve performansın düşmesini engelleyebiliyoruz. Bunu yaparken dikkat edilmesi gereken birkaç noktaya da değinelim. Havuzun başlangıç boyutunu oyunumuzun ihtiyaçlarına göre iyi belirlememiz önemli. Çok küçük bir havuz, sürekli yeni nesne oluşturulmasına neden olabilir; çok büyük bir havuz ise gereksiz bellek kullanımı anlamına gelir. O zaman yaptığımız işlemin performansa istenen yönde bir etkisi olmaz. Ayrıca nesnelerin durumunu da iyi takip etmeliyiz. Nesneler mutlaka tekrar kullanıma uygun hale getirilmeli. Örneğin, mermiler hedefe ulaştığında veya belirli bir süre geçtikten sonra havuza geri dönmeli. Son olarak da nesneleri havuza iade ederken, bunları devre dışı bırakmayı unutmamamız gerekiyor. Bu, nesnelerin gereksiz yere hesaplama yapmasını engeller.
  • Tekrar tekrar kullanılan nesneleri önbelleğe alarak yeni nesne oluşturma işlemlerinden de kaçınmamız gerekiyor.

Bellek Kullanımı İzleme

  • Unity Profiler ile bellek kullanımını izleyip gereksiz bellek tahsislerini belirleyebiliriz.
  • GC (Garbage Collection) işlemlerini de minimize etmemiz gerekir. Gereksiz bellek tahsisini önleyerek GC’nin devreye girmesini azaltabilirsek, bu da performansa olumlu yönde katkı sağlar.

5. Kod Optimizasyonu

Verimli Kod Yazımı

  • LINQ (Language Integrated Query), veriler üzerinde sorgular yapmayı kolaylaştırıyor ancak performans maliyeti yüksek.Bu sebeple yüksek performans beklediğimiz kısımlarda LINQ yerine klasik döngüleri ve koşulları kullanmak daha avantajlı olabilir.
  • C# dilinde bellek yönetimi, Garbage Collector (GC) tarafından gerçekleştiriliyor. Yeni nesneler oluşturulduğunda bellek tahsis ediliyor ve bu nesneler kullanılmadığında GC tarafından temizleniyor. Ancak, gereksiz bellek tahsisleri ve buna bağlı olarak gereksiz oluşturulan nesnelerin silinmeye çalışılması performansı olumsuz etkileyebilir.

Asenkron İşlemler

  • Async ve Await: Ağ işlemleri veya disk okuma/yazma gibi uzun süren işlemleri asenkron olarak gerçekleştirmek ana oyun döngüsünün kesintisiz çalışmasını sağlar.

Sonuç olarak Unity’de performans optimizasyonu, oyunlarımızın daha akıcı ve verimli çalışmasını sağladığından büyük öneme sahip. Ben de bu makalede performansımızı artırmamıza yardımcı olacak teknikler ve ipuçlarını anlatmaya çalıştım. Bu ipuçlarını uygulayarak, oyuncularımıza daha iyi bir oyun deneyimi sunabileceğimizi umuyorum.

Hepimize iyi kodlamalar.

Teşekkürler.

Selin.

Hiç yorum yok: