Unity Profiler Kullanımı

Yayınlandı: 26 Mart 2020 yasirkula tarafından Oyun Tasarımı, UNITY 3D içinde

Merhabalar,

Unity‘de yaptığınız oyunların zaman zaman istediğiniz akıcılıkta çalışmadığı, performans sıkıntıları yaşadığı durumlar olmuştur. Sorunun kaynağını bazen tahmin yoluyla bulabilirsiniz ancak her zaman bu kadar şanslı olamayabilirsiniz. Neyse ki Unity’nin bize sağladığı Profiler penceresi ile performans sıkıntılarını tespit etme sürecini oldukça hızlandırabilirsiniz. Bu derste de Profiler’a genel olarak göz atacağız.

Hazırsanız kemerleri bağlayın, çünkü uzun bir yolculuğa çıkıyoruz!

Profiler penceresine Window-Profiler veya Window-Analysis-Profiler ile ulaşabilirsiniz. Profiler’ı iki farklı şekilde kullanabilirsiniz: oyunu editörde test ederken veya oyunu build aldıktan sonra cihazınızda test ederken. Unity’nin önerdiği yöntem ikincisi, çünkü oyunu editörde test ederken editörün kullandığı CPU/GPU kaynakları, Profiler’ın gösterdiği verileri yanlış etkileyebilir. Ayrıca mobil için yaptığınız bir oyun bilgisayarın GPU’sunda (editörde) sıkıntısız çalışırken, mobil cihazda test ederken takılabilir. Bu durumda oyunu editörde test ederken Profiler’ı çalıştırsak, oyun editörde takılmadığı için sıkıntının kaynağını bulamayabiliriz.

Oyunu editörde test ederken Profiler kullanmak için, Profiler penceresindeki Record butonunun açık olduğundan emin olup oyunu çalıştırabilirsiniz. Oyun başladıktan sonra Profiler penceresine veri gelmeye başladığını göreceksiniz.

Build aldığınız oyunu cihazda test ederken Profiler kullanmak için, File-Build Settings‘teki Development Build ve Autoconnect Profiler seçenekleri seçili iken Build & Run yapmanız yeterli. Oyun cihazda açıldığında Profiler’a otomatik olarak veri gelmesi lazım (mobilde test ederken cihazı bilgisayara USB ile bağlamanız lazım). Eğer veri gelmiyorsa, Profiler penceresindeki Record butonunun açık olduğundan ve Active Profiler olarak cihazın seçili olduğundan emin olun:

Profiler penceresi 3 ana parçadan oluşmaktadır:

  1. Menü barı: Profiler’ı kontrol etmeye yarayan birkaç butonu barındırır.
    • Record: aktifse Profiler veri toplar, değilse toplamaz
    • Deep Profile: aktifse Profiler biraz daha performans harcar ama çok daha detaylı veri toplar, sıkıntıları tespit ederken nokta atışı yapmaya yardımcı olur. Ancak Unity 2019.3’ten önceki sürümlerde, oyunu cihazda test ederken Deep Profile desteklenmemektedir (2019.3 ve sonrasında ise, Build Settings‘teki Deep Profiling seçili iken build almanız lazım)
    • Profile Editor: aktifse Unity’nin Hierarchy, Inspector vb. panellerinden de veri toplanır, yani adı üstünde editörün kendisi debug edilir. Ben hiç bu seçeneği açma ihtiyacı duymadım
    • Clear: Profiler’da gösterilen mevcut tüm verinin temizlenmesini sağlar
    • Save ve Load: Profiler’da gösterilen tüm veriyi bir dosyaya kaydetmeye (Save) ve daha sonra tekrar bu dosyadan çekmeye (Load) yarar
    • Frame: Profiler’da seçili olan frame’in hangi frame olduğu yazar. Profiler sadece seçili frame hakkında detaylı bilgi gösterir. Hemen yanı başındaki ok tuşları ile seçili frame’i bir ileri veya bir geri alabileceğimiz gibi, Current butonu ile de en son frame’i seçebiliriz
  2. Modüller: Profiler’ın topladığı veriler farklı kategoriler (modül) altında gösterilir. Her bir modül de kendi içinde veriyi alt kategorilere ayırır. Örneğin CPU Usage modülü, Rendering, Scripts, Physics vb. alt kategorilere sahiptir. Her bir alt kategori, modülün sağındaki grafikte ayrı bir renk ile gösterilir. Alt kategorileri, isimlerinin solundaki karelere tıklayarak grafikten gizlemek mümkündür. İlaveten, bazı modüllerde alt kategorileri sürükle-bırak yaparak kendi içinde sıralayabilir, böylece grafikteki yukarıdan aşağıya sıralarını değiştirebilirsiniz. Grafiğin herhangi bir yerine tıklayarak, tıkladığınız frame’i seçili hale getirebilirsiniz.
  3. Modül detayları: Profiler’ın en can alıcı noktası. Mevcut seçili olan frame hakkında detaylı bilgi burada gösterilir. Hangi modülün seçili olduğuna göre, burada gösterilen bilgiler de değişir. İstediğiniz modüle (CPU Usage, GPU Usage vb.) tıklayarak, o modülün detaylı verilerine erişebilirsiniz.

Profiler penceresinde genel olarak dikkatinizi çekmek istediğim birkaç nokta var:

  • Modülleri sağ üstlerindeki çarpı işaretine tıklayarak gizleyebilirsiniz. Çoğu zaman Profiler’ın gösterdiği modüllerin büyük bir kısmına ihtiyaç duymazsınız, bu modülleri gizleyerek boş yere kalabalık yapmalarını engelleyebilirsiniz. İlaveten, ne kadar az modül açıksa Profiler o kadar az CPU harcar (özellikle oyunu cihazda test ederken daha kritik öneme sahip). Gizlediğiniz modülleri tekrar göstermek için, menü barındaki Add Profiler butonunu kullanabilirsiniz
  • GPU Usage modülü, ekran kartının kullanımı hakkında veri gösterir ama her cihazda desteklenmez. Desteklenmediği durumlarda bu modülde “GPU profiling is not supported by the graphics card driver” mesajını görürsünüz. Eğer oyunu editörde test ederken de bu mesajı görüyorsanız, editörü yeniden başlatmayı deneyebilirsiniz
  • GPU Usage modülünün desteklendiği durumlarda, modül detayları kısmında hem CPU hem de GPU’nun seçili frame’de kaç milisaniye harcadığını görebilirsiniz (aksi taktirde sadece CPU’nun milisaniyesini görebilirsiniz). Bu, oyunu kastıran sorunun CPU tabanlı mı (CPU bound) yoksa GPU tabanlı mı (GPU bound) olduğunu bulmanıza yardımcı olur: hangisi daha çok milisaniye harcıyorsa sıkıntı ondadır. Örneğin alttaki resimde, GPU’yu optimize etmemiz gerektiğini görebiliriz:

Gelgelelim Profiler’ın bize gösterdiği verileri anlayıp analiz etmeye. Profiler kullanırken vaktinizin büyük çoğunluğunu CPU Usage modülünde harcayacaksınız, o yüzden onunla başlamak istiyorum.

CPU Usage Modülü

Bu modül, CPU (işlemci) kullanımını analiz etmeye yarar. Yazdığımız tüm C# script’ler işlemcide çalışır ve CPU’ya etkileri burada gözükür.

Bu modülün detaylarına 3 farklı modda bakabiliriz:

1. Hierarchy

Veriler alt alta dizilir ve gruplara ayrılır. Grupların solundaki oklara tıklayarak, o grubun içindeki verileri görmek mümkündür. Örneğin üstteki resimde WaitForTargetFPS bir grup değilken Camera.Render, Canvas.SendWillRenderCanvases, BehaviourUpdate vs. bir gruptur. Bu modda her satır, CPU’yu kullanan farklı bir sample‘ı (unsur, numune, faktör, eleman) temsil eder ve her sütun da bu sample ile ilgili rakamsal verileri gösterir:

  • Overview: CPU’yu kullanan bu sample’ın ney olduğuyla ilgili bize ipucu veren bir açıklama
  • Total: bu sample’ın, seçili frame’deki CPU kullanımının % kaçından sorumlu olduğunu gösterir
  • Self: Total ve Self sütunlarında gösterilen değerler, gruplarda farklılık gösterir. Total sütununda grubun tamamının CPU’nun % kaçını kullandığı gözükürken, Self sütununda ise grubun içindeki sample’lar hesaba dahil olmaz, sadece mevcut satırın CPU’nun % kaçını kullandığı gözükür
  • Calls: bu sample’ın seçili frame’de kaç defa çalıştığını gösterir. Üstteki resimde FPSDisplay.Update‘in Calls’u 1 çünkü sahnede bu script’ten sadece 1 tane vardı. Ancak eğer 2 objede FPSDisplay script’i olsaydı, bu satırın Calls’unda 2 görecektik çünkü FPSDisplay’in Update fonksiyonu o frame’de 2 farklı kez çalışmış olacaktı
  • GC Alloc: bu sample’ın seçili frame’de kaç byte ekstra RAM harcadığını gösterir. Bu değer 0’dan uzaklaştıkça oyunun performansı olumsuz etkilenir, özellikle de bu değer tek bir frame’de değil de her bir frame’de 0’dan büyükse. GC (garbage collector), özellikle mobil oyunlarda çok önemli bir nokta olduğu için, bu konuyla ilgili optimizasyon dersimde daha detaylı bahsettim: https://yasirkula.com/2016/06/19/unity-optimizasyon-onerileri/
  • Time ms: bu sample’ın seçili frame’de kaç milisaniye CPU harcadığını gösterir
  • Self ms: Total ve Self sütunları arasındaki farklılık, Time ms ve Self ms sütunları için de geçerli
  • Uyarılar: kullanıldığını görmedim

İstediğiniz bir sütunun ismine tıklayarak, satırları o sütuna göre sıralayabilirsiniz.

2. Raw Hierarchy

Hierarchy’den tek farkı, bu modda her satırın Calls değeri 1’dir. Yani Hierarchy’de bir sample’ın Calls değeri 3 idiyse, Raw Hierarchy’de o sample tek bir satır ile temsil edilmez de 3 farklı satır ile temsil edilir. Ben bu mod yerine Hierarchy modunu tercih ediyorum.

3. Timeline

Hierarchy modunda sample’lar alt alta dizilirken, bu modda ise soldan sağa doğru dizilirler. Hangi sample daha önce çalıştıysa o sample daha solda yer alır. Yani sample’lar çalışma sıralarına göre sıralanırlar. Hierarchy modundaki gruplar ise burada da alt alta dizilirler. Örneğin Hierarchy modunda FPSDisplay.Update sample’ı, BehaviourUpdate grubunun içinde yer almaktadır. Üstteki resminde de görüleceği üzere, FPSDisplay sample’ı Timeline’da da BehaviourUpdate sample’ının bir alt satırında yer almaktadır.

Timeline modunun Hierarchy moduna göre en büyük avantajı, Main Thread harici thread’lerin de CPU’yu nasıl kullandıklarını görebilmenizdir. Örneğin üstteki resimde Render Thread‘in Gfx.ProcessCommands sample’ını çalıştırdığını, Worker Thread‘lerin ise hemen hemen sürekli Idle olduklarını, yani bir iş yapmadıklarını görebiliriz. Bu değerleri Hierarchy modunda göremeyiz.

Timeline veya Hierarchy modunda herhangi bir sample’a tıklarsanız, grafikte o sample parlak renkle vurgulanır. Böylece o sample’ın tüm frame’lerde ne kadar CPU harcadığını görebilirsiniz. Örneğin:

1. resimde hiçbir şey seçili değilken 2. resimde ise Camera.Render sample’ını seçtim. Resimde görüldüğü üzere, Camera.Render tüm frame’lerin yaklaşık olarak yarısını işgal ediyor. Bu sample’ın ait olduğu alt kategoriler ise Rendering ve Others‘tır. Bu sample’ın birden çok alt kategoriye dahil olmasının sebebi, Camera.Render’ın Hierarchy’de aslında bir grup olmasıdır. Bu grubun içindeki sample’ların bir kısmı Rendering’e dahilken bir kısmı da Other’a dahildir.

Hierarchy modundayken, modül detaylarının sağ üst köşesindeki buton ile, Show Related Objects ve Show Calls pencerelerini açmak mümkündür:

Show Related Objects penceresi sadece oyunu editörde test ederken işe yarar (yazının devamında bahsedeceğim GC.Alloc istisnası hariç). Eğer seçili sample sahnedeki bir GameObject ile bağdaşıyorsa, o obje bu listede gözükür:

Show Calls penceresinde ise, seçili sample’ı hangi sample’ların çağırdığı (Called From) ve seçili sample’ın hangi sample’ları çağırdığı (Calls To) gözükür:

Şimdi dilerseniz CPU Usage modülünde en sık gördüğümüz sample’lara bakalım.

Ana Sample’lar

  • EditorLoop: sadece oyunu editörde test ederken gözükür. Editörün kaç milisaniyelik iş yaptığını gösterir (Scene, Inspector ve Hierarchy panellerini ekrana çizmek gibi). Menü barındaki Profile Editor seçeneği açıksa, bu sample bir grup haline gelir ve içine girerek editörün nerelerde CPU harcadığı görülebilir. Eski Unity sürümlerinde bu sample Overhead olarak gözükür. Eğer Overhead bir anda çok fazla CPU harcamaya başladıysa, editörü yeniden başlatmayı deneyebilirsiniz
  • PlayerLoop: oyunun kendisinin ne kadar CPU harcadığını gösterir. Sağlıklı değerler almak için, oyunu editörde değil de cihazda test etmeniz lazım çünkü editörde bilgisayarın güçlü CPU ve GPU’sundan faydalanılır ve EditorLoop yüzünden editörün kendisi de Profiler’da gözüken değerlere etki eder
  • Profiler.CollectEditorStats: Profiler’ın veri toplarken CPU’yu ne kadar yorduğunu gösterir. Bu grubun içindeki Profiler.CollectGlobalStats, oyunu editörde test ederken de cihazda test ederken de gözükür ancak diğer alt sample’lar sadece editöre hastır

Script Sample’ları

  • Update.ScriptRunBehaviourUpdate: yazdığınız script’lerdeki Update fonksiyonları ve Unity’nin kendi bazı component’lerindeki Update fonksiyonları bu grup altında listelenir
  • BehaviourUpdate: Update.ScriptRunBehaviourUpdate ile aynı ancak dokümantasyonda yazdığına göre, Update.ScriptRunBehaviourUpdate aynı zamanda coroutine’lerin işlenmesini de hesaba katıyormuş
  • CoroutinesDelayedCalls: çalışmakta olan coroutine’ler burada listelenir
  • PreLateUpdate.ScriptRunBehaviourLateUpdate: çalışmakta olan LateUpdate fonksiyonları burada listelenir
  • FixedBehaviourUpdate: çalışmakta olan FixedUpdate fonksiyonları burada listelenir

Render (Görüntü Alma) ve VSync Sample’ları

  • WaitForTargetFPS: eğer Application.targetFrameRate ile hedef fps değeri belirlediyseniz (mesela 30fps veya 60fps), oyunun bu fps değerine uymak için kaç milisaniye beklediğini gösterir. Eğer VSync kapalı ise (Edit-Project Settings-Quality-V Sync Count), Profiler’da bunun olması İYİ bir şeydir, bunun anlamı oyununuz hedeflediğiniz fps değerinden daha yüksek bir fps’i yakalayacak kadar performanslı çalışıyordur ama hedeflediğiniz fps’e uymak için CPU’yu bir miktar uykuda bekletiyordur. Bu da CPU’nun daha az yorulması demektir. Eğer VSync açık ise, WaitForTargetFPS oyunun VSync’e uymak için ne kadar beklediğini gösterir. VSync bazı durumlarda oyunu kastırabildiği için, VSync açıkken bu sample’ı kesin olarak iyiye yoramayız
  • Gfx.ProcessCommands: Timeline modundayken Render Thread altında gözükür ve Render Thread’in yaptığı tüm işler bu grup altında listelenir. Performans için, Unity CPU’da birden çok thread çalıştırır. Bizim yazdığımız script’lerin büyük çoğunluğu ana thread’de (Main Thread) çalışır. Kameranın görüş alanındaki objelerin GPU’ya yollanarak ekrana çizilmesi işini ise Render Thread yapar. Bu süreçte Main Thread’den Render Thread’e, GPU’ya ne tarz işler yaptırması gerektiğini söyleyen bir takım komutlar (command) yollanır. Render Thread de bu komutları işleyerek (process) GPU’ya iletir
  • Gfx.WaitForCommands: Render Thread‘in GPU’ya yeni komutlar göndermeye hazır olduğu, yani Main Thread‘den yeni komutlar beklediği ve bu esnada herhangi bir iş yapmadığı zaman dilimlerini ifade eder. Eğer oyununuz hedeflediğiniz fps’i yakalayamıyorsa ve Timeline’da Gfx.WaitForCommands büyük bir yer kaplıyorsa, bu durum Main Thread’in fazla yorulduğu anlamına gelebilir; performansı iyileştirmek için Main Thread’i en çok yoran sample’ların tespit edilip optimize edilmesi gerekir (mesela kendi yazdığınız bir script çok milisaniye harcıyorsa, bu script’i başka thread’lerde çalıştırmayı düşünebilirsiniz; bkz. multi-threading)
  • Gfx.PresentFrame: GPU’nun mevcut frame’i ekrana çizmesinin ne kadar sürdüğünü gösterir. Eğer VSync açıksa, bu sample’ın WaitForTargetFPS ile senkronize olan kısmı, VSync’i beklediğimiz zaman dilimini gösterir
  • Gfx.WaitForPresent: Main Thread‘in Render Thread‘e yeni komutlar yollamaya hazır olduğunu, ancak GPU henüz elindeki tüm komutları işlemeyi bitirmediği için, Render Thread’in Main Thread’den yeni komutlar almaya hazır olmadığını gösterir. Gfx.WaitForPresent esnasında Render Thread’in neyle meşgul olduğunu görmek için, Timeline modunu kullanabilirsiniz.
    • Eğer Render Thread Camera.Render ile meşgulse, Render Thread’in komutları draw call olarak GPU’ya iletmesi veya texture’ları GPU’ya yüklemesi uzun vakit alıyor demektir; yani oyununuz CPU’yu GPU’dan daha çok yoruyordur (CPU bound). Bu durumda draw call sayısını azaltmanız (Game panelinin sağ üstündeki Stats‘ta yer alan Batches‘tan gözükebilir), oyununuzdaki texture’ların çözünürlüğünü düşürmeniz ve texture’ların Generate Mip Maps seçeneğini açmanız işe yarayabilir. İlaveten, Edit-Project Settings-Player-Graphics Jobs seçeneğini açmayı da deneyebilirsiniz
    • Eğer Render Thread Gfx.PresentFrame ile meşgulse, oyununuz GPU’yu CPU’dan daha çok yoruyor olabilir (GPU bound) veya VSync‘i bekliyor olabilir. Bu durumda VSync’i kapatmayı veya oyununuzdaki materyal ve shader’ları optimize etmeyi deneyebilirsiniz (mobil oyunlarda Standard shader’ı mümkün olduğunca kullanmayın, Mobile ve Legacy kategorilerindeki shader’ları kullanın)
  • Gfx.WaitForRenderThread: Render Thread‘in henüz elindeki tüm komutları işlemeyi bitirmediğini ve bu yüzden Main Thread‘in Render Thread’i beklediğini ifade eder

Multi-threading İle Alakalı Sample’lar

  • Idle: Timeline modunda, Worker Thread‘lerde gözükür. O thread’in bir iş yapmadığı zaman dilimini ifade eder
  • Semaphore.WaitForSignal: mevcut thread’in başka bir thread’i beklediğini gösterir. Hangi thread’in beklendiğini tespit etmek için, Timeline’da Semaphore.WaitForSignal’ın bittiği andan çok kısa bir süre önce, diğer thread’lerden hangisindeki bir sample bitiyor onu bulmalısınız
  • WaitForJobGroupID: ECS (entity component system) kullanan bir Worker Thread‘in yapmakta olduğu işi bitirdiği, ancak aynı ECS işini yapan diğer Worker Thread’ler henüz işlerini bitirmediği için o thread’leri beklediği süreyi gösterir. Bu esnada, Unity bu Worker Thread’i başka bir işle görevlendirebilir

Fizik Sample’ları

  • Physics.Simulate: fizik motorunun çalışmasını tetikler
  • Physics.Processing: Cloth component’leri hariç tüm fizik objeleri burada işlenir
  • Physics.ProcessingCloth: Cloth component’leri burada işlenir
  • Physics.FetchResults: fizik motorunun döndürdüğü sonuçların toplandığı sample
  • Physics.UpdateBodies: tüm Rigidbody‘lerin position ve rotation değerleri, Physics.Processing‘de yapılan hesaplamalar sonucu bulunan değerlerle (Physics.FetchResults) güncellenir
  • Physics.ProcessReports: tüm FixedUpdate‘ler çalıştıktan sonra çalışır. 4 farklı alt sample’dan oluşur:
    • Physics.TriggerEnterExits: OnTriggerEnter ve OnTriggerExit fonksiyonları çağrılır
    • Physics.TriggerStays: OnTriggerStay fonksiyonları çağrılır
    • Physics.Contacts: OnCollisionEnter, OnCollisionExit ve OnCollisionStay fonksiyonları çağrılır
    • Physics.JointBreaks: aşırı güç uygulama sonucu kırılan (break) Joint component’leri ile ilgili hesaplamalar yapılır
  • Physics.UpdateCloth: nasıl Physics.UpdateBodies tüm Rigidbody’leri güncelliyorsa, bu sample’da tüm Cloth component’lerini günceller
  • Physics.Interpolation: Interpolate değeri None olmayan Rigidbody’lerin position ve rotation değerlerini tekrar hesaplar

GC.Alloc Sample’ı

Garbage Collector (GC), özellikle mobil oyunlarda optimizasyonuna daha çok önem verilmesi gereken bir unsurdur. Optimizasyon dersimin başında garbage collector’dan bir miktar bahsettim, öncelikle o kısmı okuyarak kabaca garbage collector’un ne olduğunu anlamanızı öneririm: https://yasirkula.com/2016/06/19/unity-optimizasyon-onerileri/

GC.Alloc sample’ı, Hierarchy modunda hangi grubun içinde yer alıyorsa, o grubun o frame’de kaç byte ekstra RAM kullandığını gösterir (örneğin yeni bir obje Instantiate edilmiş veya yeni bir List/array oluşturulmuş olabilir). Tek bir frame’de birden çok GC.Alloc sample’ı olabilir, hangi sample’lar o frame’de RAM harcadıysa, genelde her birisinin içerisinde bir tane de GC.Alloc sample’ı yer alır. Bu sample’ları tespit etmenin en kolay yolu, Hierarchy modunda satırları GC Alloc sütununa göre sıralamaktır (bazı sample’ların GC Alloc değeri 0’dan büyük olmasına rağmen içinde GC.Alloc alt sample’ı olmayabilir, bu sample’ları da GC.Alloc’muş gibi varsayabilirsiniz).

Deep Profile açık değilken GC.Alloc’u neyin tetiklediğini tespit etmek her zaman kolay olmayabilir çünkü Deep Profile kapalıyken Profiler verileri çok derine inmezler. Deep Profile’ın dezavantajı ise yavaş olmasıdır. Neyse ki GC.Alloc’ların kaynağını bulmak için Deep Profile’dan daha güzel bir yöntem mevcut (oyunu cihazda test ederken bu yöntem sadece Unity 2019.3 ve sonrasında çalışır, daha önceki sürümlerde maalesef bu yöntem sadece editörde çalışır). Test amaçlı, her frame’de yeni bir array oluşturan şöyle bir script yazıp bunu kamerama verdim:

using UnityEngine;

public class TestScript : MonoBehaviour
{
	void Update()
	{
		ArrayOlustur();
	}

	void ArrayOlustur()
	{
		int[] test = new int[10];
	}
}
  • Unity 2019.3 ve sonrası: menü barındaki Call Stacks butonunu aktif hale getirin. Ardından Hierarchy modunda bir GC.Alloc’a tıklayıp Show Related Objects menüsünü açın ve N/A satırına tıklayın:

Timeline modunu kullanıyorsanız da, Timeline’daki kırmızı renkli GC.Alloc sample’larına tıklayabilirsiniz:

  • Unity 2018.4 ve sonrası: menü barındaki Allocation Callstacks butonuna tıklayıp değerini Managed Allocations yapın. Ardından yukarıda bahsettiğim yöntemlerle GC.Alloc’un sorumlusunu bulabilirsiniz
  • Unity 2017.2 ve sonrası: Timeline modundayken modül detaylarının sağ üstündeki Allocation Callstacks butonuna tıklayıp değerini Managed Allocations yapın. Ardından Timeline’daki kırmızı renkli GC.Alloc sample’larına tıklayarak detaylı bilgiye erişebilirsiniz:

El Yapımı Sample’lar

Bazen yazdığınız bir C# script’in çok fazla milisaniye harcadığını görmenize rağmen, script’in tam olarak neresinin bundan sorumlu olduğunu bulamayabilirsiniz çünkü Deep Profile kapalıyken toplanan veri çok derine inmez. Bu durumlarda kodunuzun belli bir kısmının Profiler’da ayrı bir sample olarak gözükmesini sağlayabilirsiniz.

Kendi sample’ınızı oluşturmak için, kodunuzun hangi kısmını sample yapmak istiyorsanız o kısmı Profiler.BeginSample ve Profiler.EndSample fonksiyonları arasına alabilirsiniz:

UnityEngine.Profiling.Profiler.BeginSample( "Ornek Sample" );

// Buraya yazılan tüm kodlar, Profiler'da "Ornek Sample" ismi ile gözükecek
BirFonksiyon();
BaskaBirFonksiyon();
Debug.Log( "Merhaba Dünya: " + Time.time );

UnityEngine.Profiling.Profiler.EndSample();

Örneğin TestScript‘i şu şekilde güncelledim:

using UnityEngine;

public class TestScript : MonoBehaviour
{
	void Update()
	{
		UnityEngine.Profiling.Profiler.BeginSample( "Array Olusturma" );
		ArrayOlustur();
		UnityEngine.Profiling.Profiler.EndSample();

		UnityEngine.Profiling.Profiler.BeginSample( "Yeni String Fonksiyonu" );
		StringBirlestir();
		UnityEngine.Profiling.Profiler.EndSample();
	}

	void ArrayOlustur()
	{
		int[] test = new int[10];
	}

	void StringBirlestir()
	{
		string str = "";
		for( int i = 0; i < 1000; i++ )
			str += i;
	}
}

Profiler’ın öncesi ve sonrasını aşağıdaki resimde görebilirsiniz:

Memory Modülü

Bu modül, oyunun ne kadar RAM kullandığını analiz etmeye yarar. Oyunu editörde test ederken burada gözüken değerler normalden daha yüksek olabilir çünkü editörün kendisi de bir miktar RAM kullanır ve bu ister istemez Profiler’a yansır.

Öncelikle modülün grafiğinde gözüken değerlere göz atalım:

  • Total Allocated: oyunun kullandığı toplam RAM miktarı
  • Texture Memory: hafızadaki Texture’ların kullandığı toplam RAM miktarı
  • Mesh Memory: hafızadaki 3D modellerin (mesh) kullandığı toplam RAM miktarı
  • Material Count: hafızadaki toplam materyal sayısı
  • Object Count: hafızadaki toplam obje sayısı (kullanılan asset’ler ve sahnedeki objeler)
  • Total GC Allocated: heap hafızasındaki objelerin boyutu (string, array vs. gibi class objeleri heap’te tutulur, ancak Texture, Mesh, AudioClip vs. asset’ler buraya dahil değildir)
  • GC Allocated: bu frame’de heap hafızasının ne kadarının daha kullanıldığını gösterir

Memory modülünün detaylarına iki farklı modda bakılabilir:

1. Simple

Yeni objeler oluştururken, işletim sisteminden sürekli biraz daha fazla RAM istememek için, Unity ihtiyacı olandan biraz daha fazla RAM’i rezerve eder ve yeni bir obje oluşturunca önce rezerve ettiği RAM’i kullanmaya çalışır. Bu RAM de dolduysa ancak o zaman işletim sisteminden daha çok RAM istenir. Simple modundaki ilk satır, kullanılmakta olan RAM’i (Used) gösterirken ikinci satır ise rezerve edilmiş olan RAM’i (Reserved) gösterir. İkinci satırdaki değerlerden ilk satırdaki değerleri çıkararak, rezerve edilmiş ama henüz kullanılmayan RAM miktarı bulunabilir. Bu satırlardaki değerlere gelecek olursak:

  • Total: toplam kullanılan RAM miktarı
  • Unity: asset’lerin kapladığı alan
  • Mono: heap hafızasındaki objelerin boyutu (grafikteki Total GC Allocated ile aynı değer ancak benim paylaştığım iki screenshot farklı frame’lerden alındığı için, değerleri bende aynı değil)
  • GfxDriver: grafik kartı sürücüsünün Texture, shader, 3D model ve RenderTexture’lar için kullandığı yaklaşık RAM miktarı
  • Audio: Unity’nin ses sisteminin kullandığı RAM miktarı
  • Video: Unity’nin video sisteminin (VideoPlayer, MovieTexture) kullandığı RAM miktarı
  • Profiler: Profiler’ın kendisinin kullandığı RAM miktarı

Diğer satırlara bakacak olursak da:

  • Total System Memory Usage: işletim sisteminin Unity için ne kadar RAM ayırdığını gösterir. İşletim sistemi bu değeri çekmeyi desteklemiyorsa, burada 0 byte yazar
  • Textures, Meshes (3D modeller), Materials, AnimationClips (animasyonlar) ve AudioClips (ses dosyaları): hafızada bu asset’lerden kaç tane olduğunu ve kapladıkları toplam alanı yazar
  • Assets: hafızadaki toplam asset sayısı
  • GameObjects in Scene: sahnedeki GameObject sayısı
  • Total Objects in Scene: sahnedeki toplam obje sayısı (GameObject’ler, component’ler vs.)
  • Total Object Count: hafızadaki toplam obje sayısını gösterir. Gözlemlerime göre bu değer, Assets ile Total Objects in Scene‘in toplamına eşittir. Ayrıca grafikteki Object Count da bu değerle aynıdır
  • GC Allocations per Frame: bu frame’de fazladan ne kadar heap hafızası kullanıldığını gösterir (grafikteki GC Allocated ile aynı değer)

2. Detailed

RAM’deki objeleri görmeye yarar. RAM’de hangi objelerin olduğunu bulup bunlarla ilgili veri toplamak uzun süren bir işlem olduğu için, bu işlemin Detailed butonunun sağındaki Take Sample butonuna tıklayarak elle başlatılması gerekir. Seçili frame hangisi olursa olsun, Take Sample butonu daime en son frame’in (mevcut frame) RAM bilgilerini gösterir. Eğer Gather object references butonu seçili ise, soldaki pencerede seçili olan objenin kullanıldığı yerler sağdaki pencerede listelenir. Böylece belli bir asset’in niye RAM’de olduğunu görebilirsiniz.

Detailed modundaki kategoriler şunlardır:

  • Other: asset, GameObject veya Component olmayan objeler burada listelenir
  • Builtin Resources: editörün kullandığı asset’ler veya Edit-Project Settings-Graphics-Always Included Shaders gibi, oyun boyunca RAM’de kalan asset’ler burada listelenir
  • Assets: oyunun hafızaya aldığı asset’ler burada listelenir
  • Scene Memory: sahnedeki objeler ve sahip oldukları component’ler burada listelenir
  • Not Saved: hideFlags değeri DontSave olan objeler burada listelenir

Rendering Modülü

Game panelinin sağ üstündeki Stats‘ın gösterdiği değerler, aynı zamanda burada da gösterilir. Oyunu cihazda test ederken Stats penceresine erişmek mümkün olmadığı için, bu modül özellikle oyunu cihazda test ederken işe yarar.

  • SetPass Calls: kameranın görüş alanındaki farklı materyal sayısı arttıkça bu değer artar. Eğer gölgeler açıksa bu değer yaklaşık ikiye katlanabilir ve sahnedeki objeler aynı anda kaç farklı ışıktan etkileniyorsa, bu değer doğru orantılı olarak artar. Grafik kartı performansını en çok etkileyen faktörlerden birisi budur, o yüzden bu değeri olabildiğince düşük tutmak önemlidir
  • Draw Calls: kameranın görüş alanındaki obje sayısı ve ışık sayısı arttıkça bu değer artar. Ayrıca birden çok adımda (pass) çizilen karmaşık shader’lar da bu değeri artırabilir
  • Total Batches: henüz Draw Calls‘tan farklı olduğunu görmedim
  • Tris: kameranın görüş alanındaki objelerin toplam üçgen (triangle) sayısı
  • Verts: kameranın görüş alanındaki objelerin toplam köşe (vertex) sayısı
  • Dynamic Batching: aynı materyale sahip low-poly objeleri Unity’nin GPU’ya yollamadan önce birleştirme çabasıdır. Böylece GPU daha az iş yapar ama Dynamic Batching bir miktar CPU harcar (gereksiz olduğu durumlarda Edit-Project Settings-Player‘dan kapatılabilir)
    • Batched Draw Calls: Draw Calls‘un ne kadarının Dynamic Batching ile tek bir seferde GPU’ya yollandığını gösterir
    • Batches: Dynamic Batching’in kaç kez işe yaradığını gösterir. Örneğin üstteki resimde Batched Draw Calls 11 ve Batches 4; bu durumda Dynamic Batching ilk başta 4, sonra 2, sonra 3 ve sonra da 2 Draw Call’u birleştirmiş olabilir (sayıları örnek olarak verdim)
    • Tris: Dynamic Batching’in birleştirdiği objelerin toplam üçgen sayısı
    • Verts: Dynamic Batching’in birleştirdiği objelerin toplam köşe sayısı
  • Static Batching: Inspector’undaki Static kutucuğu işaretli GameObject’leri, Unity’nin oyunu build alırken birleştirerek tek bir obje yapma çabasıdır. Böylece bu objeler daha az Draw Call ile ekrana çizilebilir ancak RAM kullanımı biraz artar
  • Instancing: GPU Instancing‘in desteklendiği platformlarda, materyalindeki Enable Instancing değeri açık objelerin tek bir seferde ekrana çizilmesi olayıdır. Örneğin kameranın görüş alanında 1000 tane meteor varsa, bunların hepsi aynı materyali kullanıyorsa ve bu materyalin Enable Instancing’i açıksa, GPU Instancing‘in desteklendiği platformlarda bu 1000 meteor tek bir draw call ile ekrana çizilebilir
  • Used Textures: GPU’nun kullandığı toplam Texture sayısı ve bunların boyutları
  • RenderTextures: GPU’nun kullandığı toplam RenderTexture sayısı ve bunların boyutları
  • Shadow Casters: kameranın görüş alanındaki gölge düşüren obje sayısı
  • Diğer parametreleri ben de bilmiyorum

Open Frame Debugger butonuna tıklayarak, mevcut frame’deki tüm draw call’ları tek tek inceleyebileceğiniz Frame Debugger penceresini otomatik olarak açabilirsiniz.

GPU Usage Modülü

GPU (ekran kartı) kullanımını analiz etmeye yarar. Her platformda desteklenmez. Desteklendiği platformlar şurada mevcuttur: https://docs.unity3d.com/Manual/ProfilerGPU.html

CPU Usage modülündeki Hierarchy ve Raw Hierarchy modları ile Show Related Objects ve Show Calls pencereleri burada da mevcuttur.

Burada bilmeniz gereken kavramlar şunlar:

  • Opaque: opak, saydam olmayan objeler. Bu objelerin materyallerinin Render Queue‘leri genel olarak Geometry, yani 2000’dir. Opak objeler, kameraya yakın objeden kameraya uzak objeye doğru çizilirler; böylece depth buffer sayesinde, öndeki bir objenin arkasında kalan objelerin pikselleri GPU tarafından direkt yoksayılır
  • Transparent: saydam objelerdir. Bu objelerin materyallerinin Render Queue‘leri genel olarak Transparent, yani 3000’dir. Saydam objeler, kameraya uzak objeden kameraya yakın objeye doğru çizilirler; böylece arkada kalan saydam objenin renkleri, önde kalan saydam objenin renklerine etki eder. Saydam objeler depth buffer optimizasyonundan opak objeler kadar faydalamadıkları için GPU’yu daha çok yorarlar, bu yüzden de gereksiz saydam objelerden kaçınılmalıdır
  • Shadows/Depth: gölgelerin hesaplanarak ekrana çizilmesi
  • Deferred PrePass ve Deferred Lighting: deferred rendering ile alakalı olduğunu düşünüyorum. Mobil projeler deferred rendering değil de forward rendering kullandığı için, onlarda bu değerlerin bir önemi olduğunu sanmıyorum
  • PostProcess: adı üstünde, post-processing efektlerini temsil eder (blur, depth of field, ambient occlusion vb.)
  • Other: tam olarak neleri kapsadığını ben de bilmiyorum ama sadece editöre has GPU kullanımı ve VSync‘in beklenmesi gibi durumlar bu kategoriye giriyor olabilir

Bu modülde karşımıza çıkan sample’larla ilgili bilgi veremiyorum çünkü Unity’nin dokümantasyonunda bu sample’lardan bahsedilmiyor. Ancak çoğu önemli sample yukarıdaki terimleri kullandığı için, kabaca sample’ların ne hakkında olduğunu anlayabilirsiniz diye ümit ediyorum.

Physics Modülü

Fizik motoru ile ilgili bir takım istatistikleri listeler:

  • Active Dynamic: Kinematic olmayan ve uyku modunda olmayan Rigidbody’lerin sayısını gösterir. Bir Rigidbody belli bir süre boyunca hareket etmez ve başka objelerle temasa geçmezse, bu Rigidbody’nin fizik motorunu boş yere yormaması için Unity bunu otomatik olarak uyku moduna alır. Uyku modundaki Rigidbody’ler hemen hiç performans harcamazlar ve bir temas olursa otomatik olarak uyandırılırlar
  • Active Kinematic: Kinematic olan ve uyku modunda olmayan Rigidbody’lerin sayısını gösterir. Birkaç frame boyunca Rigidbody.MovePosition veya Rigidbody.MoveRotation‘ı çağrılmayan kinematic Rigidbody’ler uyku moduna girerler. Eğer bu Rigidbody’e bağlı Joint component’leri varsa, joint’lerin sayısıyla doğru orantılı olarak buradaki değer artar
  • Static Colliders: kendisinde veya parent objelerinin herhangi birinde Rigidbody olmayan Collider‘ların sayısını gösterir. Fizik motoru bu collider’ları statik olarak varsayar ve ona göre optimizasyonlar yapar; ancak eğer bu collider’lar hareket ederse, bu fizik motorunu oldukça yorar. Bu yüzden hareket eden her Collider’ın kendisinde veya parent’larının birinde Rigidbody olduğundan emin olun
  • Rigidbody: uyuyan veya uyanık toplam Rigidbody sayısı
  • Trigger Overlaps: Is Trigger‘ı işaretli olan temas halindeki Collider çifti sayısı
  • Active Constraints: bu değerin nasıl hesaplandığını bilmiyorum ama sahnedeki Joint sayısı ve temas halindeki obje sayısı arttıkça bu değer de artıyor
  • Contacts: temas halindeki Collider çifti sayısını gösterir, bu değere Trigger Overlaps de dahildir

Fizik motoru Edit-Project Settings-Time-Fixed Timestep‘te belirlenen periyotta çalıştırılır. Örneğin bu değer 0.02 ise, fizik motoru saniyede 50 kez çalıştırılır. Periyot ne kadar kısa olursa, fiziksel etkileşimler o kadar pürüzsüz çalışır ancak oyunun fps’inin düştüğü durumlarda, fizik motoru bu periyotu yakalamak için tek bir frame’de birden çok kez çalışabilir. Bunu CPU Usage modülünde Physics.Processing‘in Calls‘undan tespit etmek mümkündür (bu değer 1’den büyükse, o frame’de fizik motoru birden çok kez çalışmıştır):

Zaten fps düşükken bir de fizik motorunun birden çok kez çalışması, fps’i daha da aşağılara sürükleyebilir. Bu durumu iyileştirmek için ya en başta fps’i düşüren faktörler optimize edilmeli, ya da Edit-Project Settings-Time‘daki Maximum Allowed Timestep‘in değeri azaltılarak, fizik motorunun ne olursa olsun bu değerden daha çok milisaniye harcamasının önüne geçilmeli.

Physics2D Modülü

2 boyutlu fizik motoru ile ilgili bir takım istatistikleri listeler:

  • Total Bodies: sahnedeki toplam Rigidbody2D sayısı
  • Active Bodies: uyanık Rigidbody2D sayısı (Rigidbody’lerin uyumasından Physics modülünde bahsettim)
  • Sleeping Bodies: uyku modundaki Rigidbody2D sayısı
  • Dynamic Bodies: Body Type‘ı Dynamic olan Rigidbody2D sayısı
  • Kinematic Bodies: Body Type‘ı Kinematic olan Rigidbody2D sayısı
  • Static Bodies: Body Type‘ı Static olan Rigidbody2D sayısı
  • Contacts: temas halindeki Collider2D çifti sayısı
  • Discrete Island Count: fizik motoru daha iyi performans için tüm temasları (contact) birkaç gruba (island) böler, böylece multi-threaded çalışırken her gruptaki temasları başka bir thread işleyebilir. Rigidbody2D’sinin Collision Detection Mode‘u Discrete olan temasların kaç gruba ayrıldığı burada gösterilir
  • Continuous Island Count: Rigidbody2D’sinin Collision Detection Mode‘u Continuous olan temasların kaç gruba ayrıldığını gösterir
  • Discrete Bodies: Collision Detection Mode‘u Discrete olan Rigidbody2D sayısı
  • Continuous Bodies: Collision Detection Mode‘u Continuous olan Rigidbody2D sayısı
  • Joints: sahnedeki Joint2D component’i sayısı
  • Static Shapes: fizik motoru, Collider2D‘leri shape adındaki bileşenlere ayırır. BoxCollider2D tek bir bileşenden oluşurken, PolygonCollider2D ise karmaşıklığına göre birden çok bileşenden oluşabilir. Buradaki değer, Body Type‘ı Static olan Rigidbody2D’lerdeki bileşen sayısını gösterir
  • Active Shapes: Body Type‘ı Static olmayan ve uyanık olan Rigidbody2D’lerdeki bileşen sayısı
  • Sleeping Shapes: Body Type‘ı Static olmayan ve uyku modunda olan Rigidbody2D’lerdeki bileşen sayısı

UI ve UI Details Modülleri

Bu modüller, Unity’nin UI (arayüz) sistemi ile ilgili bir takım istatistikleri listelerler:

Modülün grafiğinde yer alan değerlere bakacak olursak:

  • Layout: arayüz elemanlarının pozisyon ve ebatlarının kaç milisaniyede hesaplandığını gösterir. HorizontalLayoutGroup gibi layout component’leri bu süreci oldukça yavaşlatabilir
  • Render: arayüz elemanlarının ekrana çizilmesinin ne kadar sürdüğünü gösterir
  • UI Batches: arayüzün kaç aşamada (batch) ekrana çizildiğini gösterir. Bir batch’te birden çok UI objesi topluca ekrana çizilebilir
  • UI Vertices: arayüzün geometrisinin kaç köşeden (vertex) oluştuğunu gösterir
  • Markers: arayüzle etkileşime geçildiğinde, bu etkileşimlerin ney olduğunun grafikte gözükmesini sağlar. Örneğin bir Toggle‘ın değerini değiştirince, grafikte Toggle.value marker’ı belirir

Modül detaylarındaki satırları yukarıdan aşağıya gezerek, sağdaki pencereden UI’ın aşama aşama nasıl ekrana çizildiğini görebiliriz. Buradaki sütunlar şunlardır:

  • Object: ekrana çizilen tüm Canvas’lar ve bunların ekrana çizilme aşamaları (batch) burada gözükür
  • Self Batch Count: bu Canvas’ın kaç batch’te ekrana çizildiğini gösterir. Eğer canvas’ın içinde child canvas'(lar) varsa (nested canvas), bu nested canvas'(lar)ın batch sayısı bu değere dahil değildir
  • Cumulative Batch Count: bu canvas’ın ve içindeki tüm nested canvas’ların toplam batch sayısı
  • Batch Breaking Reason: bir önceki satırdaki batch ile bu satırdaki batch’in niye tek bir batch olarak ekrana çizilemediği, bu batch’leri ayrı ayrı ekrana çizmeye sebep olan etken burada gözükür. Örneğin:
    • Not Coplanar With Canvas: batch’teki objelerden birisinin RectTransform‘unun Rotation X veya Rotation Y değeri 0’a eşit değildir
    • CanvasInjectionIndex: bir CanvasGroup component’i, batch’in birleştirilmemesini uygun görmüştür
    • Different Material Instance: iki batch’teki objeler farklı materyal kullanmaktadır
    • Different Rect Clipping: iki batch’teki objeler farklı Mask veya RectMask2D objelerinin child’ıdırlar
    • Different Texture: iki batch’teki objeler farklı texture’lara sahiptir. Sprite atlas kullanarak bu sayıyı önemli miktarda azaltabilirsiniz. Optimizasyon dersimde sprite atlas’lardan kabaca bahsettim: https://yasirkula.com/2016/06/19/unity-optimizasyon-onerileri/
    • Different A8TextureUsage: iki batch’teki objelerin texture’larının alpha kanalına aynı yöntemle erişmek mümkün değildir
  • GameObject Count: bu batch ile tek seferde ekrana kaç UI objesinin çizildiğini gösterir
  • GameObjects: GameObject Count‘a dahil olan objeler burada listelenir. Bu satıra çift tıklayarak, batch’teki objeleri Hierarchy’den otomatik olarak seçebilirsiniz

Sağdaki önizleme penceresinde her bir batch’in içeriğini görsel olarak görebilirsiniz. Detach butonuna tıklayarak, bu pencereyi daha büyük bir şekilde görebilirsiniz. Bir sağındaki buton ile, pencerenin arkaplan rengini değiştirebilirsiniz: Checkerboard (siyah beyaz kare döşemeli zemin), Black (siyah arkaplan) ve White (beyaz arkaplan). En sağdaki buton ile de, 3 farklı görünümden birini seçebilirsiniz:

  1. Standard: UI objeleri normal bir şekilde gözükür
  2. Overdraw: UI objelerinin overdraw‘a etkileri gözükür. Üst üste binen UI objesi sayısı arttıkça overdraw artar; overdraw’un çok artması performansı olumsuz etkiler
  3. Composite overdraw: gözlemlediğim kadarıyla Overdraw görünümünün farklı renkler kullanan hali; ben başka bir fark bulamadım

Audio Modülü

Unity’nin ses sistemi ile ilgili bir takım istatistikleri listeler:

Grafikte gördüğümüz değerler şunlardır:

  • Playing Audio Sources: seçili frame’de kaç AudioSource‘un bir ses çalmakta olduğunu gösterir
  • Audio Voices: çalmakta olan toplam ses sayısını gösterir. AudioSource’un PlayOneShot fonksiyonu ile, tek bir AudioSource kullanarak birden çok ses çalmak mümkün olduğundan, bu değer Playing Audio Sources‘tan yüksek olabilir
  • Total Audio CPU: ses sisteminin ne kadar CPU harcadığını gösterir
  • Total Audio Memory: ses sisteminin ne kadar RAM (memory) harcadığını gösterir

Modül detayları iki pencereden oluşmaktadır. Soldaki pencere vasıtasıyla, ses sisteminin hangi kısımlarının ne kadar CPU ve RAM (memory) harcadığını görebiliriz. Buradaki Paused Audio Sources, herhangi bir ses çalmayan AudioSource sayısını gösterir. Sağdaki pencerede ise, çalmakta olan tüm seslerin listesini görebiliriz.

Modül detaylarının yukarısındaki Channels and groups ile, sağdaki pencerede listelenen sesleri gruplara ayırabiliriz ancak anladığım kadarıyla bu grup olayı sadece AudioMixer asset’i kullanıyorsanız işe yarıyor. Reset play count on play ise, sağdaki pencerenin Plays sütunundaki değerlerin oyunu her yeniden başlattığınızda sıfırlanmasını sağlar. Gelgelelim sağdaki pencerede yer alan sütunlara:

  • Object: sesi çalan AudioSource objesi
  • Asset: çalınan AudioClip asset’i; herhangi bir satıra tıklayarak Project panelinden Asset’in, Hierarchy panelinden de Object’in seçilmesini sağlayabilirsiniz
  • Volume: AudioSource’un ses düzeyi
  • Audibility: sesin duyulmakta olan düzeyi; bu değeri hesaplarken Volume, AudioSource’un AudioListener‘a olan uzaklığı ve varsa AudioMixer‘ın ses düzeyi dikkate alınır
  • Plays: AudioClip’in şimdiye kadar kaç kere oynatıldığını gösterir
  • 3D: AudioSource’un Spatial Blend değerinin 3D olup olmadığı (3D seslerin şiddeti, AudioListener sesin kaynağından uzaklaştıkça azalır ancak 2D sesler için bu söz konusu değildir)
  • Paused: AudioSource’un duraklatılıp duraklatılmadığını gösterir
  • Muted: AudioSource’taki Mute seçeneğinin açık olup olmadığı
  • Virtual: Unity’nin aynı anda oynatabildiği ses sayısı sınırlıdır (Edit-Project Settings-Audio-Max Real Voices). Bu sınır aşıldıktan sonra, seslerin bir kısmı arkaplanda ileri sarılmaya devam eder ancak biz bu sesleri duymayız; bu sesler için Virtual sütunun değeri YES olur, duyulmakta olan (Max Real Voices‘a dahil olan) sesler için ise NO olur. Virtual seslerin de bir limiti vardır, bu limite Edit-Project Settings-Audio-Max Virtual Voices‘tan erişebilirsiniz
  • OneShot: sesin AudioSource.PlayOneShot ile çalınıp çalınmadığını gösterir
  • Looped: AudioSource’un Loop seçeneğinin açık olup olmadığını gösterir. OneShot sesler için bu değer NO‘dur
  • Distance: AudioListener’ın AudioSource’a olan uzaklığı, 2D sesler için bu değer N/A’dır
  • MinDist: AudioSource’un Min Distance değeri, 2D sesler için bu değer N/A’dır
  • MaxDist: AudioSource’un Max Distance değeri, 2D sesler için bu değer N/A’dır
  • Time: sesin kaçıncı saniyesinde olduğumuz
  • Duration: sesin toplam uzunluğu

Ve böylece bir dersin daha sonuna gelmiş bulunmaktayız. Sonraki derslerde görüşmek dileğiyle!

Yararlanılan Kaynaklar

Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Google fotoğrafı

Google hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.