Unity Kod Optimizasyonu ile RAM’e Hükmedin

Muhammed İKİNCİ
FastnTech
Published in
5 min readJul 30, 2020

Selamlar, bu yazımızda Unity kod optimizasyonu hakkında detaylı bilgi vereceğiz. Çeşitli durumlar için geçerli pek çok optimizasyon çeşidi bulunuyor.

Object Pooling

Nesne Birleştirme ve Nesne Oluşturma olarak da geçiyor. Burada amaç en başta, kullanılacak nesneleri oluşturmak ve yok etmeden tekrar kullanmak. Çoğu zaman yapılan en büyük yanlışlardan biri bu oluyor.

Prefab kullanılacağı zaman ‘Instantiate’ metodu ile bir kopyası oluşturuluyor. Objenin işi bittikten sonra ise tamamen yok ediliyor. Bu işlemler tek seferlik yapıldığı zaman pek sorun gibi durmasada tekrar edildiğinde çok fazla bellek kullanımına yol açıyor.

Bu aşamada ‘Object Pooling’ devreye giriyor. Amacını yukarıda özetlemiştik. Şimdi ise biraz detaylandıralım ve örneklemelere geçelim.

Eskiden bir ‘Shooter’ oyunu yaptıysanız silahların mermilerini her seferinde yeniden klonlar ve işleri bittiğinde ise onları yok ederdiniz. Object Pooling ile kullanılacak mermileri sahne başlangıcında oluşturuyoruz ve aktifliklerini kapatıyoruz.

Artık bir mermi havuzumuz var tıpkı şarjör gibi. Silah her ateşlendiğinde mermi klonlamak yerine havuzda bulunan bir mermi çekilir, pozisyonu değiştirilir ve aktif hale getirilir. İşi bittiğinde ise pasif hale getirilir. Bu sayede objeler sadece başlangıçta oluşturulur ve asla yok edilmez.

Örnek göstermeye başlayalım. Öncelikle objelerin zaten sahnede olduğu durumu canlandırıyoruz. Kullanılacak objelerimizin hepsi başta sahnemizde yer alıyor.

Bu nesnelerimizin sadece aktiflikleri kapalı.

Tüm objeleri yine manuel olarak scriptimizde bulunan listeye atayalım.

Spawn işlemi için bir coroutine oluşturuyor ve başlatıyoruz.

Objemizi LinQ ile aktiflik durumuna göre çekiyoruz (Performans bakımından LinQ kullanmanız önerilmez). Null kontrol yapıyor, aktifliğini açıyoruz ve sonrasında kullanımdan kalan velocitysini sıfırlıyoruz.

Object Pooling genel olarak bu şekilde kullanılıyor. Objelerin tekrar kullanılmak üzere sahnede saklanması sizlere çok fazla performans artışı sağlayacaktır.

Update vs Coroutine

Unity’de sürekli ya da belirli bir süre sonra yapılacak işlemler için Coroutineleri kullanabiliyoruz. Bazı durumlarda ise Update içerisine yazdığımız kodları Coroutine içerisine yazmak performans bakımından çok daha avantajlı bir hale gelebiliyor. Arada çok üst düzey bir fark var mı derseniz tepkimelere ve bellek kullanımlara bakıldığında üst düzey bir ayrım göremezsiniz. Ancak çoğu durumda Update kullanmanın gereksizliğini ortaya koyacak derecede esneklik sağlayan Coroutinelerin özellikleri güzel bir geliştirme avantajı da sunuyor. Gelin beraber bu ufak farklara bakalım.

Object Pooling de zaten bir Coroutine başlatmıştık. StartCoroutine fonksiyonu ile bir routine başlatabiliyoruz. Coroutinelerde iş akışını durdurmak istiyorsak aşağıdaki gibi bir kullanım yapabiliyoruz.

Bu kod satırı sayesinde, 5 saniyelik bir bekleme sonrasında kodlarımız çalışmaya devam ediyor.

İstersek başladığı karenin bitmesini beklemesini de söyleyebiliriz.

While ile kullanarak Update gibi bir çağrı elde edebiliriz.

İşte bu durumlarda Update yerine kullanmak avantajlı duruma getiriyor bizleri. Update içerisinde çeşitli conditionlar yazmak ya da farklı farklı fonksiyonları kullanılmasalar çağırarak her seferinde ek yüklerin ortaya çıkmasına neden oluyoruz. Birden fazla Coroutine oluşturarak her akışın kendine ait bekleme noktalarına sahip olmasını sağlayabiliriz.

Her akışı farklı düzende kontrol edebiliriz. Tek bir akış oluşturup tekrar limitlerini belirleyebiliriz. Bunların çoğunu Update fonksiyonunda yapamıyoruz çünkü akışı rahat kontrol edemiyor, koşul mekanizmaları oluşturuyoruz. Mekanizmalar oluşturmak için çeşitli koşullar geliştirmemiz gerekiyor ve de kodların çalışmasını engellemek için bir yerden kesmek. Bu durumda ise Update çığrından çıkabiliyor.

String.Empty

String oluştururken herhangi bir değer girilmediğinde “” tırnak kullanarak boş olarak tanımlarız. Ancak bu atamayı yaptığımızda string bellekte yerini alır ve nesne artık oluşturulmuştur.

String.Empty kullanıldığında ise nesne empty alana referans verilir. Yani bellekte zaten olan bir alanı referans olarak gösterir. Bu sayede ekstra yer kaplamamış olur.

String.Emptynin kullanımı String.IsNullOrEmpty fonksiyonunu da beraberinde getiriyor. Null veya uzunluğu 0 olan objeleri rahatlıklı kontrol etmek amacıyla kullanılan bir fonksiyondur. Her iki durumu da destekler.

String.Empty ile ilgili detaylı bilgiye ECMA dokümanlarından erişebilirsiniz.

Caching Components

GetComponent fonksiyonu ile aldığımız Component’lar bir değişkene atarak tekrar kullanılabilir. GetComponent objeye erişmek için çok fazla güç harcıyor. Objenin bir referansını oluşturup sonrası için de kullanmak çok daha mantıklı.

Finding Objects

Obje aramalarında en çok yapılan kullanılanlar GameObject.Find ve GameObject.FindWithTag fonksiyonları. Bu fonksiyonların kullanımı çok maliyetlidir ancak Find fonksiyonunun maliyeti tüm objeler için yaptığı aramadan dolayı daha fazladır. FindWithTag araması Find aramasına nazaran çok daha az maliyetlidir.

Bir obje aramak yerine direkt slota assign etmek yukarıda bulunan iki yöntemden çok daha kullanışlıdır.

Camera.Main

Bu fonksiyon yüksek maliyetli, aktif kamerayı getiren bir Unity API çağrısıdır. Finding Objects kısmında belirttiğimiz fonksiyonlardan pek bir farkı bulunmamaktadır. Hepsi bellekte bulunan tüm objeleri gezer. Bunları önlemek amacıyla bu fonksiyonların döndürdüklerini cachelemek gerekiyor ve bir daha kullanmamak gerekiyor.

Local Declare Garbage

Çalıştırılacak fonksiyonlar içerisinde kullanılan değişkenlerin tanımlamaları fonksiyon içerisinde yapılıyorsa değişken her seferinde belleğe yazılır eski adresine tanımlanmaz. Bu sebeple büyük bir şişme gerçekleşir. Performansı etkiler.

Bu durumda her zaman farklı bir array oluşur. Bunun yerine aşağıdaki şekilde bir kullanım yapmamız çok daha iyi olacaktır.

Unity’de hangi platform için çalışırsanız çalışın, Unity kod optimizasyonu uygulamanız sizlerin yararına olacaktır. Daha birçok optimizasyon çeşidi ve durumu bulunmaktadır. Bunları projelerinizde ihtiyaç doğrultusunda kullanabilir ve öğrenebilirsiniz.

Unity kod optimizasyonu yapmak için yeterli tecrübeniz ve bilgi birikiminiz yoksa, FastnTech olarak size yardımcı olabiliriz.

--

--