T: tema · Z: kodu büyüt · S: konuşmacı notları · F: tam ekran · Esc: genel bakış · ⌂ ders haritası
OYUNLARDA YAPAY ZEKÂ · HAFTA 18
Oyun YZ’sinde Performans
Kare bütçesi, zaman dilimleme, YZ LOD’u, olay tabanlı güncelleme, DOTS ve Mass — binlerce NPC’yi 16 milisaniyeye sığdırmak
PRESS ▶ TO START

Bu derste oyunun haritası 🗺️

  1. Bütçe — 60 FPS’de bir karede ne kadar zamanımız var, YZ’ye ne kadarı düşer?
  2. Önce ölç — profilleyiciler, işaretçiler, kayıt ve görselleştirme (Final Fantasy XV), otomatik testler; Cities: Skylines II’nin “dişleri”
  3. Zaman dilimleme ve kuyruklar — işi karelere yaymak, yol isteklerini sıraya koymak
  4. YZ LOD’u — LOD Trader ve Assassin’s Creed Unity’nin 10.000 kişilik kalabalığı
  5. Olaylar, önbellek, uzaysal yapılar — hesaplanabilen şeyi güncelleme
  6. Veri odaklı tasarım ve iş parçacıkları — Unity DOTS, Unreal Mass
  7. Kod — zaman dilimli zamanlayıcı, Jobs + Burst, profil + dört laboratuvar
  8. Araçlar — Unity Profiler, Unreal Insights, Godot, Tracy
🎮 Bu dersin sonunda…

…YZ’nin kare süresindeki payını ölçebilecek, pahalı işleri karelere yayıp kuyruğa alabilecek, NPC’leri önemlerine göre farklı ayrıntıda çalıştırabilecek ve “bu optimizasyon gerçekten gerekli mi?” sorusunu veriyle cevaplayabileceksiniz.

🤔 ISINMA: 500 NPC, KİŞİ BAŞI 10 IŞIN

Her NPC her karede çevresini görmek için 10 ışın (raycast) atıyor. Sahnede 500 NPC var ve oyun 60 FPS. Saniyede kaç ışın?

  • 500 × 10 × 60 = 300.000 ışın/saniye. Bir ışın birkaç mikrosaniye sürse bile bu, karenin büyük bir kısmı.
  • Ama oyuncu aynı anda en fazla birkaç NPC’ye bakıyor. Uzaktaki bir köylünün görüşünü saniyede 60 kez yenilemek kimin işine yarıyor?
  • Oyun YZ’si performansının özü: doğru işi, doğru sıklıkta, doğru ayrıntıda yapmak. Ve bunu tahminle değil ölçerek yapmak.

🎯 Bu konu için bilmeniz gerekenler

Yeşil = gerekli · kesikli = faydalı ama şart değil. Tıklayınca ilgili sunuma gider.

Neden?Bu ders algoritmalar dersinin “büyüme hızı” fikrinin oyundaki karşılığı: n NPC için O(n²) komşu arama ile ızgara arasındaki fark, kare süresinde milisaniyeler demek. Olay tabanlı güncelleme bir öncelik kuyruğu (yığın) kullanır.
🧰 Kodlamadan korkuyorsanızProfilleyiciyi açıp bir grafiğe bakmayı ve bir döngünün kaç kez çalıştığını saymayı bilmek yeter. DOTS ve iş parçacıkları için tanıtım düzeyinde kalacağız.

Mini sözlük

frame budget · frame timekare bütçesi · kare süresiBir karede harcanabilecek süre (60 FPS → 16,7 ms) · gerçekte harcanan süre
spike · hitch · 1% lowsıçrama · takılma · en kötü %1Tek bir karenin çok uzaması · oyuncunun hissettiği donma · en yavaş karelerin ortalaması
profiler · markerprofilleyici · işaretçiKodun nerede ne kadar süre harcadığını ölçen araç · ölçülecek kod bölümü
time slicing · staggeringzaman dilimleme · kademelendirmeİşi birden çok kareye yaymak · ajanların güncellemelerini farklı karelere dağıtmak
LOD (level of detail)ayrıntı düzeyiÖnemsiz şeyi daha ucuz/seyrek hesaplamak
starvationaçlıkBir ajanın sırası hiç gelmemesi
spatial partitioninguzaysal bölümlemeIzgara, dörtlü ağaç: “yakınımda kim var?” sorusunu hızlandıran yapılar
DOD · ECS · cache missveri odaklı tasarım · varlık-bileşen-sistem · önbellek ıskasıVeriyi işlenme biçimine göre düzenlemek · Unity DOTS mimarisi · işlemcinin veriyi bellekten beklemesi
LEVEL 0
Bütçe: 16,7 ms
zaman en kıt kaynak
  • bütçe: 16,7 ms
  • önce ölç
  • zaman dilimleme ve kuyruklar
  • YZ LOD’u
  • olaylar, önbellek, uzaysal yapılar
  • veri odaklı tasarım ve iş parçacıkları
  • kod ve laboratuvarlar
  • araçlar ve entegrasyon

Kare bütçesi

hedefkare başına
30 FPS (bazı konsol oyunları)33,3 ms
60 FPS (çoğu oyun)16,7 ms
120 FPS (rekabetçi, VR’ye yakın)8,3 ms
  • Bu süreye her şey sığmalı: girdi, fizik, animasyon, ses, ağ, oyun kodu, YZ, çizim hazırlığı.
  • YZ’ye genelde birkaç milisaniyelik bir dilim düşer (oyuna göre değişir; strateji oyunlarında daha fazla).
  • Ortalama değil en kötü kare önemlidir: ortalama 12 ms ama arada bir 40 ms olan bir oyun “takılıyor” diye hissedilir.
YZ zamanı nereye gider?
  • Algılama: görüş ışınları, ses sorguları (Y11)
  • Yol bulma: A* aramaları, navmesh sorguları (Y8, Y9)
  • Konum sorguları: EQS/TPS gibi çok sayıda aday noktanın test edilmesi (Y12)
  • Karar: davranış ağacı, utility, GOAP planlama (Y3–Y5)
  • Hareket: steering, komşu arama, çarpışmadan kaçınma (Y7, Y10)
Genelde en pahalıları ışınlar ve yol bulma; karar mantığı çoğu zaman şaşırtıcı derecede ucuzdur.

Çizimle: 16,7 ms nereye gidiyor?

60 FPS’te bir kare: 16,7 ms (örnek bir aksiyon oyunu, işlemci tarafı)girdi 0,5oyun kodu2,0 msfizik3,0 msanimasyon2,2 msYZ2,0 msses 0,8çizim (işlemci tarafı)4,0 msboşluk2,2 ms↑ YZ’nin payı ≈ 2 ms500 NPC → NPC başına 0,004 ms = 4 mikrosaniyeSayılar temsilîdir; oyuna göre çok değişir. Ama oran hep benzer: YZ, kareyi başka altı işle paylaşır. Bütçe aşılırsa kare gecikir ve oyun “takılır”.
💡 Günlük hayattanBir öğrencinin günü 24 saat: uyku, okul, yol, yemek… Ödeve kalan 2 saat. Ödevin uzarsa bir şeyden kısmak zorundasınız. YZ’nin karedeki 2 ms’si de o 2 saatlik ödev zamanı gibi: sabit ve başkalarıyla paylaşılıyor.
Quiz 1 · bütçe
Oyununuzun ortalama kare süresi 11 ms, ama her 3–4 saniyede bir 45 ms’lik kareler var. Oyuncu ne hisseder ve ilk şüpheli ne olmalı?
Göz, ortalamayı değil tutarsızlığı fark eder. Periyodik sıçramaların klasik sebebi, birçok sistemin aynı karede tetiklenmesidir: bütün NPC’lerin aynı anda yeniden plan yapması, aynı saniyede başlayan zamanlayıcılar. Çözüm: işi kademelendirmek ve kuyruğa almak (Level 2).
LEVEL 1
Önce ölç
tahmin etme, ölç
  • bütçe: 16,7 ms
  • önce ölç
  • zaman dilimleme ve kuyruklar
  • YZ LOD’u
  • olaylar, önbellek, uzaysal yapılar
  • veri odaklı tasarım ve iş parçacıkları
  • kod ve laboratuvarlar
  • araçlar ve entegrasyon

Ölçmeden optimize etmeyin

  • Donald Knuth’un ünlü uyarısı: “Erken optimizasyon bütün kötülüklerin anasıdır.” Zamanın çoğu kodun küçük bir bölümünde harcanır; hangisi olduğunu tahminle bulmak zordur.
  • Profilleyici: Unity Profiler, Unreal Insights, Godot’nun profilleyicisi. Her sistemin kare başına süresini ve çağrı sayısını gösterir.
  • İşaretçiler: kendi kodunuzun bölümlerini adlandırın (“AI.Perception”, “AI.Path”): profilleyicide ayrı satır olarak görünür.
  • Sayaçlar: kare başına ışın sayısı, açılan A* düğümü, aktif NPC. Süre dalgalanır; sayılar sebebi gösterir.
  • Hedef cihazda ölçün: geliştirme bilgisayarı oyuncunun telefonundan 10 kat hızlı olabilir.
Kayıt ve görselleştirme: Final Fantasy XVMatthew W. Johnson ve arkadaşları (Game AI Pro 3, 3. bölüm): yüzlerce kişilik ekipte NPC hareket sorunlarını bulmak için oyun olayları bir veritabanına kaydedildi ve web tabanlı bir arayüzde harita üzerinde incelendi: takılan NPC’ler, olayların zaman ve mekândaki dağılımı, navmesh’in zamanla değişimi.
Otomatik YZ testleriMalte Skarupke (Game AI Pro Online 2021): YZ hatalarının çoğu iki karakterle yeniden üretilebilir. Küçük test seviyeleri + otomatik testler, hem hataları hem de performans gerilemelerini erken yakalar.

Efsane mi, gerçek mi? Cities: Skylines II’nin “dişleri”

  • Ekim 2023’te çıkan şehir kurma oyunu ciddi performans sorunlarıyla eleştirildi. Çıkıştan bir gün sonra bir Reddit gönderisi, vatandaş modellerinin tek tek modellenmiş dişlerle ve ayrıntı düzeyi (LOD) olmadan çizildiğini gösterdi; “oyun dişler yüzünden yavaş” fikri hızla yayıldı.
  • Geliştirici Colossal Order: dişlerin performans sorununun asıl sebebi olmadığını, ama karakterlerin LOD modellerinin eksik olduğunu ve bunun performansı etkilediğini açıkladı; LOD, su simülasyonu ve arazi gibi alanlarda iyileştirmeler yapıldı.

Durum: “Dişler oyunu yavaşlattı” → büyük ölçüde efsane. “Eksik LOD performansı düşürdü” → gerçek.

DersGözle görülür, akılda kalıcı bir “suçlu” bulmak kolaydır; asıl sebebi bulmak ölçüm ister. Profilleyici açılmadan yapılan tartışmalar (oyuncu forumlarında da, ekip içinde de) çoğu zaman yanlış yeri işaret eder. Bir de: görülmeyen ayrıntıya harcanan her milisaniye, görünen bir şeyden çalınmıştır. LOD’un mantığı bu.
LEVEL 2
Zaman dilimleme ve kuyruklar
işi karelere yaymak
  • bütçe: 16,7 ms
  • önce ölç
  • zaman dilimleme ve kuyruklar
  • YZ LOD’u
  • olaylar, önbellek, uzaysal yapılar
  • veri odaklı tasarım ve iş parçacıkları
  • kod ve laboratuvarlar
  • araçlar ve entegrasyon

Önce günlük hayattan: bir garson, otuz masa 🍽️

Tek garsonlu bir lokantada 30 masa var. Garson her dakika her masaya uğramaya çalışsa koşmaktan hiçbir siparişi alamaz. Bunun yerine sırayla dolaşır: bu dakika 1–10, sonraki 11–20, sonraki 21–30.

  • Her masa 3 dakikada bir ilgi görür; kimse fark etmez.
  • Biri el kaldırırsa (olay), garson sırayı beklemeden gelir.
  • Kapıya yakın masalara (oyuncuya yakın NPC’ler) daha sık uğrar.

Oyunda garson = YZ bütçesi, masalar = NPC’ler. Yandaki tablo 6 NPC’nin her karede ikisini düşündürür: her NPC 3 karede bir karar verir. 60 FPS’te bu, saniyede 20 karar: insandan bile hızlı.

kare 1kare 2kare 3kare 4kare 5kare 6
🧟 A🧠··🧠··
🧟 B·🧠··🧠·
🧟 C··🧠··🧠
🧟 D🧠··🧠··
🧟 E·🧠··🧠·
🧟 F··🧠··🧠

🧠 = o karede bu NPC düşünüyor (algıla + karar ver). · = önceki kararına devam ediyor (yürümeye, ateş etmeye). Her kare yalnızca 2 NPC’nin maliyeti ödenir.

Herkes her kare düşünmek zorunda değil

  • Kademelendirme: 100 NPC’yi her kare değil, her karede 10’unu güncelle. Her NPC 10 karede bir (60 FPS’de saniyede 6 kez) düşünür: çoğu karar için fazlasıyla yeterli. İnsanın tepki süresi de ~200 ms.
  • Bütçeli dilimleme: YZ’ye sabit bir süre (ör. 2 ms) ver; süre dolana kadar sıradakileri güncelle, kalanlar sonraki kareye.
  • Kuyruk: pahalı istekler (yol, konum sorgusu) bir kuyruğa girer; her kare sınırlı sayıda işlenir. Uzun bir arama bir kareye sığmazsa kaldığı yerden sonraki karede devam eder.
TuzaklarTutarsız güncelleme (bir meşale fazladan yanar), açlık (bazı ajanların sırası hiç gelmez), her ajanın listede durmasının bile maliyeti (David “Rez” Graham, Game AI Pro Online 2021).
KoddaGraham’ın örneğindeki gibi: bir indeks kareler arasında saklanır; her kare bu indeksten devam edilir ve süre dolunca durulur. Laboratuvarda bunun öncelikli bir sürümünü yazacaksınız.
🧭 DEMOYU OKUMA KILAVUZU (bir sonraki slayt)
  1. Sol alan oyun dünyası: her nokta bir NPC. Mavi büyük nokta kamera/oyuncu (fareyle sürükleyin); çevresindeki iki kesikli halka LOD sınırları.
  2. Nokta rengi = ayrıntı düzeyi: yeşil yakın (LOD 0), mavi orta (LOD 1), gri uzak (LOD 2). Sarı büyük nokta “takip ettiğiniz” ajan: uzakta bile olsa önemli.
  3. Soluk nokta = uzun süredir düşünmemiş (bayat) ajan. Ne kadar soluksa o kadar uzun süredir güncellenmedi.
  4. Sağ grafik son 160 karenin süresi: gri taban diğer sistemler (9 ms), üstündeki mor kısım YZ. Kırmızı kesikli çizgi 16,7 ms bütçe; çizgiyi aşan kare kırmızı olur (takılma).
  5. Alttaki üç satır: son 60 karede kaç kez bütçe aşıldı, kare başına kaç ajan güncellendi, en bayat ajan kaç karedir bekliyor.

Canlı: kare bütçesi ⏱️

  1. “herkes her kare” + 400 ajan: mor YZ çubukları bütçe çizgisini aşıyor; kırmızı çubuklar pahalı yol isteklerinin sıçramaları.
  2. “zaman dilimleme”: kare süresi sabit! Ama ajan sayısını artırınca “en bayat ajan” büyüyor; soluk noktalar uzun süredir düşünmeyen ajanlar.
  3. “uzaklığa göre LOD”: oyuncuyu (mavi) kalabalığın ortasına sürükleyin: yakındaki herkes her kare güncelleniyor, bütçe yine aşılabiliyor.
  4. “LOD + bütçe”: yakındakiler ve takip ettiğiniz sarı ajan her kare; kalan bütçe en uzun süredir bekleyenlere. “Başka ajanı takip et” ile uzaktaki birini seçin: hâlâ her kare güncelleniyor mu?
  1. Sol alan oyun dünyası: her nokta bir NPC. Mavi büyük nokta kamera/oyuncu (fareyle sürükleyin); çevresindeki iki kesikli halka LOD sınırları.
  2. Nokta rengi = ayrıntı düzeyi: yeşil yakın (LOD 0), mavi orta (LOD 1), gri uzak (LOD 2). Sarı büyük nokta “takip ettiğiniz” ajan: uzakta bile olsa önemli.
  3. Soluk nokta = uzun süredir düşünmemiş (bayat) ajan. Ne kadar soluksa o kadar uzun süredir güncellenmedi.
  4. Sağ grafik son 160 karenin süresi: gri taban diğer sistemler (9 ms), üstündeki mor kısım YZ. Kırmızı kesikli çizgi 16,7 ms bütçe; çizgiyi aşan kare kırmızı olur (takılma).
  5. Alttaki üç satır: son 60 karede kaç kez bütçe aşıldı, kare başına kaç ajan güncellendi, en bayat ajan kaç karedir bekliyor.
🔎 DEMODA DENEYİN
  1. “herkes her kare” + 400 ajan: mor YZ çubukları bütçe çizgisini aşıyor; kırmızı çubuklar pahalı yol isteklerinin sıçramaları.
  2. “zaman dilimleme”: kare süresi sabit! Ama ajan sayısını artırınca “en bayat ajan” büyüyor; soluk noktalar uzun süredir düşünmeyen ajanlar.
  3. “uzaklığa göre LOD”: oyuncuyu (mavi) kalabalığın ortasına sürükleyin: yakındaki herkes her kare güncelleniyor, bütçe yine aşılabiliyor.
  4. “LOD + bütçe”: yakındakiler ve takip ettiğiniz sarı ajan her kare; kalan bütçe en uzun süredir bekleyenlere. “Başka ajanı takip et” ile uzaktaki birini seçin: hâlâ her kare güncelleniyor mu?

🔗 Başka gözle: etkileşimli anlatımlar ve yazılar

Aynı konuyu başka bir anlatımla, kendi elinizle oynayarak görmek çok işe yarar. Kartlar yeni sekmede açılır; çoğu İngilizce ama görsel ve etkileşimli.

Canlı: yol isteği kuyruğu 📨

  1. Ekranı okuyun: koyu kareler duvar. Mor alan şu an aranan yolun açtığı düğümler; yeşil çizgi yeni bulunan yol (birkaç saniyede solar). Sağda kuyruk uzunluğu, ortalama bekleme ve kare başına açılan düğüm grafiği.
  2. “📨 12 NPC aynı anda yol istesin”e bir kez basın: grafik bütçe çizgisinde düz gider, yollar sırayla belirir. Hiçbir karede sıçrama yok.
  3. Düğmeye hızlıca 5 kez basın (60 istek): kuyruk kırmızıya döner, ortalama bekleme büyür. Kare süresi hâlâ sabit; bedeli gecikme.
  4. Bütçeyi 1000 yapın: bekleme sıfıra yakın. Peki neden hep 1000 yapmıyoruz? (Her düğüm zaman demek: 1000 düğüm bir karenin YZ bütçesini tek başına yiyebilir.)
  5. Bütçeyi 20 yapın: uzun bir yol birkaç kareye yayılıyor; mor alan kare kare büyüyor. Arama kaldığı yerden devam ediyor.
🔎 DEMODA DENEYİN
  1. Ekranı okuyun: koyu kareler duvar. Mor alan şu an aranan yolun açtığı düğümler; yeşil çizgi yeni bulunan yol (birkaç saniyede solar). Sağda kuyruk uzunluğu, ortalama bekleme ve kare başına açılan düğüm grafiği.
  2. “📨 12 NPC aynı anda yol istesin”e bir kez basın: grafik bütçe çizgisinde düz gider, yollar sırayla belirir. Hiçbir karede sıçrama yok.
  3. Düğmeye hızlıca 5 kez basın (60 istek): kuyruk kırmızıya döner, ortalama bekleme büyür. Kare süresi hâlâ sabit; bedeli gecikme.
  4. Bütçeyi 1000 yapın: bekleme sıfıra yakın. Peki neden hep 1000 yapmıyoruz? (Her düğüm zaman demek: 1000 düğüm bir karenin YZ bütçesini tek başına yiyebilir.)
  5. Bütçeyi 20 yapın: uzun bir yol birkaç kareye yayılıyor; mor alan kare kare büyüyor. Arama kaldığı yerden devam ediyor.
Quiz 2 · zaman dilimleme
Yol isteklerini kare başına sınırlı düğümle işleyen bir kuyruk kurdunuz. 30 NPC aynı anda istek yapınca sonuncusu 20 kare bekliyor. Oyuncunun bunu fark etmemesi için en iyi tasarım?
Gecikme kaçınılmazsa onu gizleyin: hedefe doğru kaba bir ilk adım, bir tepki animasyonu, yakındakilere öncelik. Bütçeyi kaldırmak (A) sıçramayı geri getirir. Donan NPC (C) en göze batan seçenektir.
LEVEL 3
YZ LOD’u
önemsiz olan ucuz olsun
  • bütçe: 16,7 ms
  • önce ölç
  • zaman dilimleme ve kuyruklar
  • YZ LOD’u
  • olaylar, önbellek, uzaysal yapılar
  • veri odaklı tasarım ve iş parçacıkları
  • kod ve laboratuvarlar
  • araçlar ve entegrasyon

Çizimle: YZ’nin ayrıntı düzeyi (LOD)

uzak: yalnızca konumorta: basit kararyakın: tam YZ🧍🔭 takip edilen şüpheliuzakta ama tam YZ

Grafikte uzaktaki ağaç daha az üçgenle çizilir; kimse fark etmez. YZ’de de aynı fikir: oyuncudan uzaktaki NPC daha az düşünür.

halkane yapılır?sıklık
yakıngörüş ışınları, davranış ağacı, tam A*her kare
ortabasit kurallar, önceden pişmiş yollar5 karede bir
uzakyalnızca konum ilerler, animasyon yoksaniyede bir

Ama uzaklık her zaman doğru ölçüt değil: oyuncunun dürbünle izlediği şüpheli uzakta olsa da tam ayrıntı hak eder. Sonraki slayttaki “LOD Trader” tam bunu çözüyor.

Derin hikâye: LOD Trader, uzaklık yerine “fark edilme olasılığı”

Ben Sunshine-Hill (Game AI Pro, 14. bölüm): uzaklık eşikleri yetersizdir; kalabalık oyuncunun yanına gelirse bütçe patlar, seyrek alanlarda ise ayrıntı gereksiz yere kısılır.

  • Ölçü: oyuncunun bir gerçekçilik kırılmasını fark etme olasılığı. Üç tür: gerçek dışı durum (duvara doğru yerinde koşmak), süreksizlik (köşeyi dönünce kaybolan karakter), gerçek dışı uzun vadeli davranış (amaçsızca dolaşan karakter).
  • Her karakter için tür başına bir kritiklik: görünürlük, dikkat (oyuncu onu takip ediyor mu?)… Takip edilen şüpheli uzakta olsa bile iyi yol bulma alır; önden geçen köylü iyi animasyon.
  • Her kare, bütçeyi aşmadan toplam fark edilme olasılığını en aza indiren seçim (yaklaşık bir sırt çantası çözümü).
  • Yüzlerce karakterli açık dünya bir oyunda 8 özelliği yönetti: ortalama 57 µs/kare (%0,17). Kör deneyde izleyiciler uzaklık tabanlı LOD’daki kırılmaları daha sık fark etti.
Ana fikir“Bu karakter ne kadar uzakta?” değil, “oyuncu bu karakterdeki ayrıntı kaybını fark eder mi?” Uzaklık bunun sadece bir parçası. Y12’deki utility puanlamasının ve Y11’deki farkındalığın performans dünyasındaki karşılığı.

Derin hikâye: Assassin’s Creed Unity’nin kalabalığı (2014)

  • Fransız Devrimi Paris’i: Ubisoft, bazı görevlerde 5.000, kralın idam sahnesinde 10.000 kişilik kalabalıklar hedefledi. Kalabalık tepkileri için 500’den fazla “kalabalık hayatı” türü vardı.
  • Ama aynı anda ancak 40 “gerçek” YZ ve 120 yüksek çözünürlüklü model çalıştırılabiliyordu.
  • Çözüm (GDC 2015, “Massive Crowd on Assassin’s Creed Unity: AI Recycling”): kalabalığın büyük kısmı ucuz, düşük ayrıntılı temsillerdir; oyuncu yaklaştıkça ya da biriyle etkileşime girdikçe bu kişi bir havuzdan alınan tam YZ’ye ve yüksek çözünürlüklü modele fark ettirmeden dönüşür; uzaklaşınca kaynak geri verilir.
Havuz (pooling)Pahalı nesneleri (tam YZ beyni, ayrıntılı model) her seferinde oluşturup yok etmek yerine sabit sayıda hazırlayıp sırayla yeniden kullanmak: hem hız hem bellek için. Mermi ve parçacıklarda da standart.

🎬 Ara: Assassin’s Creed Unity’nin kalabalığı

Massive Crowd on Assassin’s Creed Unity: AI Recycling
GDC · 38 dk · YouTube’da aç

Az önceki halkaların gerçek oyundaki hâli: binlerce kişilik kalabalığın çoğu ucuz, düşük ayrıntılı temsilciler; oyuncu yaklaşınca biri havuzdan alınan “gerçek” bir YZ’ye dönüşüyor. İlk 12 dakika ana fikri veriyor.

🤔 İzlerkenKalabalıkta kaç ayrıntı düzeyi var? Bir NPC düşük düzeyden yükseğe geçerken oyuncu neyi fark edebilirdi, bunu nasıl gizlemişler? Havuzdaki YZ sayısı neden sabit?
LEVEL 4
Olaylar, önbellek, uzaysal yapılar
hesaplanabilen şeyi güncelleme
  • bütçe: 16,7 ms
  • önce ölç
  • zaman dilimleme ve kuyruklar
  • YZ LOD’u
  • olaylar, önbellek, uzaysal yapılar
  • veri odaklı tasarım ve iş parçacıkları
  • kod ve laboratuvarlar
  • araçlar ve entegrasyon

Olay tabanlı güncelleme

  • Bir NPC’nin açlığı saniyede 0,1 artıyorsa, onu her kare güncellemek yerine ne zaman acıkacağını bir kez hesaplayın ve bir öncelik kuyruğuna koyun.
  • Değer gerekirse (oyuncu NPC’ye baktı) formülle hesaplanır: açlık = başlangıç + hız · geçen süre.
  • Davranış ağaçlarında da aynı fikir: Unreal’ın olay güdümlü ağaçları (Y3) her kare kökten başlamak yerine kara tahtadaki değişikliklere tepki verir.

Önbellek, ön hesaplama, uzaysal yapılar

ÖnbellekAynı soruyu tekrar sormayın: bir konum sorgusunun sonucu birkaç kare geçerlidir (Y12); görünürlük sonucu, hedef ve gözlemci çok hareket etmediyse yeniden kullanılabilir. Sorun: “ne zaman geçersiz?” sorusu (ölü önbellek hatası).
Ön hesaplamaNavmesh pişirme (Y9), görünürlük tabloları, etki haritaları (Y12), akış alanları: oyun başlamadan ya da seyrek hesaplanır, oyun sırasında okunur. Fieldrunners 2: binlerce birim tek bir akış alanını paylaşır (Y7).
Uzaysal yapılar“Yakınımda kim var?” sorusu için herkesi herkesle karşılaştırmak O(n²): 1000 NPC → 1 milyon karşılaştırma. Izgara ya da dörtlü ağaç ile sadece komşu hücrelere bakılır (Y7’deki boids demosundaki “kontrol sayısı”nı hatırlayın).
LEVEL 5
Veri odaklı tasarım ve iş parçacıkları
DOTS, Mass, çok çekirdek
  • bütçe: 16,7 ms
  • önce ölç
  • zaman dilimleme ve kuyruklar
  • YZ LOD’u
  • olaylar, önbellek, uzaysal yapılar
  • veri odaklı tasarım ve iş parçacıkları
  • kod ve laboratuvarlar
  • araçlar ve entegrasyon

Veri odaklı tasarım: önbellek dostu kod

  • İşlemci, belleği tek tek değil satırlar hâlinde getirir. Verileriniz bellekte art arda duruyorsa hızlı; her NPC ayrı bir nesne ve her alan farklı yerdeyse işlemci zamanının çoğunu beklemekle geçirir (önbellek ıskası).
  • Nesne dizisi (AoS): her NPC’nin konum, can, durum… hepsi bir arada. Dizi nesnesi (SoA): bütün konumlar bir dizide, bütün canlar başka bir dizide. “Bütün konumları güncelle” işi SoA’da çok daha hızlıdır.
  • Mike Acton’ın CppCon 2014 konuşması “Data-Oriented Design and C++” bu yaklaşımın klasik anlatımıdır.
Nesne dizisi (AoS): bellekte“bütün konumları güncelle”: işlemci her satırda 1 işe yarar, 2 boş kutu getirirDizi nesnesi (SoA): bellekteaynı iş: getirilen satırın hepsi konum → boşa taşıma yokkonumcandurum
Motorlarda
  • Unity DOTS: Entities (ECS), C# Job System, Burst derleyicisi. Entities 1.0, Haziran 2023’te Unity 2022 LTS ile üretime hazır olarak yayımlandı. Jobs ve Burst, ECS kullanmadan da her projede kullanılabilir.
  • Unreal Mass (MassEntity): binlerce varlık için veri odaklı çerçeve; The Matrix Awakens demosunu temel alan City Sample projesinde kalabalık ve trafik bununla yönetildi.
  • Godot: sunucu API’leri (PhysicsServer, NavigationServer) ve GDExtension ile C++/Rust.
⚠️ İş parçacıklarıÇok çekirdek bedava hız değildir: iki iş parçacığı aynı veriyi aynı anda yazarsa yarış durumu. Güvenli kalıp: işler sadece kendi verisini yazar, ortak veriyi salt okunur okur; sonuçlar kare sonunda birleştirilir (Unity Jobs bunu derleme zamanında denetler).

🎬 Ara: veri odaklı tasarıma giriş

Intro to Data Oriented Design for Games
Nic Barker · 52 dk · YouTube’da aç

Az önceki AoS/SoA çiziminin uzun ve çok görsel anlatımı: işlemci önbelleği nasıl çalışır, bir oyun döngüsü neden “nesne nesne” değil “alan alan” yazılınca hızlanır. İlk 15 dakika bu sunum için yeterli.

🤔 İzlerkenVideoda önbellek ıskası kaç kat yavaşlık getiriyor? Örnekteki oyun nesnesi hangi alanlara bölünüyor? Bizim 500 NPC’lik sahnede “bütün konumları güncelle” işi hangi düzende daha hızlı olur?
Quiz 3 · DOD
2000 NPC’nin konumunu her kare güncelleyen bir sistemde profilleyici, işin hesaplamadan çok “bellek beklemekle” geçtiğini gösteriyor. En etkili değişiklik hangisi?
Bellek bekleme sorunu veri yerleşimiyle çözülür: art arda veri, önbelleğe tek seferde gelir. Unity’de binlerce ayrı Update çağrısının kendisi de maliyetlidir; ECS/Jobs ya da tek bir yönetici döngü tercih edilir.
LEVEL 6
Kod ve laboratuvarlar
zamanlayıcı, Jobs, profil
  • bütçe: 16,7 ms
  • önce ölç
  • zaman dilimleme ve kuyruklar
  • YZ LOD’u
  • olaylar, önbellek, uzaysal yapılar
  • veri odaklı tasarım ve iş parçacıkları
  • kod ve laboratuvarlar
  • araçlar ve entegrasyon

Zaman dilimli YZ zamanlayıcısı ve ölçüm (1/2)

Zaman dilimli YZ zamanlayıcısı ve ölçüm (2/2)

Unity C# Job System + Burst

Burst ile basit sayısal döngüler genelde düz C#’tan kat kat hızlı çalışır; ama ölçmeden varsaymayın. Fizik ışınları için toplu sorgu: RaycastCommand.ScheduleBatch.

🎒 Kod sözlüğü

Stopwatch · Elapsed.TotalMillisecondskronometreKod içinde süre ölçmek
ProfilerMarker · .Auto()profil işaretçisiusing bloğu süresince ölçüm; Unity Profiler’da adıyla görünür
interface IAIAgentarayüz“Think() metodu olan her şey”; zamanlayıcı türden bağımsız çalışır
struct · IJobParallelFor · Execute(i)iş yapısıHer indis için ayrı çalışan, çekirdeklere dağıtılan iş
NativeArray · [ReadOnly] · Disposeyerel diziÇöp toplayıcı dışı bellek; salt okunur işaret; elle serbest bırakma
cProfile · pstatsPython profilleyiciFonksiyon başına süre ve çağrı sayısı
performance.now()yüksek çözünürlüklü zamanTarayıcıda milisaniye ölçümü

🌱 Isınma kodu: YZ’ye kaç milisaniye kaldı?

60 FPS → 16,7 ms; 30 FPS → 33,3 ms; 120 FPS → 8,3 ms. Demodaki gri taban (“diğer sistemler”) 9 ms: 60 FPS’de YZ’ye 7,7 ms kalıyor, 120 FPS’de hiç kalmıyor. Performans konuşmalarının hepsi bu çıkarma işlemiyle başlar.

🌱 Isınma kodu: sıra bende mi?

Başlangıç kodu “10 karede bir düşün” kuralını uyguluyor ama 100 ajanın hepsi aynı karede düşünüyor: 9 kare boş, 10. kare 100 katı iş. Quiz 1’deki periyodik takılmanın ta kendisi. Çare tek bir toplama: kare numarasına ajanın numarasını ekleyin. (Kademelendirme, İngilizcesi staggering.)

🧪 Canlı laboratuvar: bu kare kimi güncelleyeyim?

İpucu: önce yakındakiler (en uzun bekleyen önce), sonra kalan yere herkesi lastUpdate’e göre sırala. Sağda sarı = bu kare güncellenen, kırmızı = 10+ karedir bekleyen.

🐍 Laboratuvar: sırayla güncelleme (round-robin)

En basit kademelendirme: her ajan n/k karede bir güncellenir, hiçbiri atlanmaz. Laboratuvardaki öncelikli seçimin temeli.

🐍 Laboratuvar: ayrıntı düzeyi seçimi

Sadece uzaklık değil, görünürlük ve dikkat de hesaba giriyor: LOD Trader’ın kritiklik fikrinin basit hâli. 0–3 seviyeleri her biri farklı güncelleme sıklığına eşlenir.

🐍 Laboratuvar: olay ne zaman olacak?

Olay tabanlı güncellemenin çekirdeği: değeri her kare artırmak yerine olayın zamanını bir kez hesaplayıp öncelik kuyruğuna koymak.
LEVEL 7
Araçlar ve entegrasyon
ölç, bütçele, izle
  • bütçe: 16,7 ms
  • önce ölç
  • zaman dilimleme ve kuyruklar
  • YZ LOD’u
  • olaylar, önbellek, uzaysal yapılar
  • veri odaklı tasarım ve iş parçacıkları
  • kod ve laboratuvarlar
  • araçlar ve entegrasyon

🧰 Kütüphaneler ve araçlar

adplatformne yapar / sınırlarınasıl eklenir
Unity Profiler · Profile AnalyzerUnityCPU/GPU/bellek zaman çizelgesi, ProfilerMarker satırları, iki ölçümü karşılaştırma; hedef cihaza bağlanarak ölçüm.Window → Analysis → Profiler; Package Manager → Profile Analyzer
Unreal Insights · stat komutlarıUnrealİz (trace) tabanlı ayrıntılı profil; stat unit, stat game, AI hata ayıklayıcısı (Gameplay Debugger).Motorla birlikte
Godot Profiler · MonitorsGodot 4Betik fonksiyonu başına süre, fizik/navigasyon sayaçları, özel monitörler.Debugger paneli
TracyC/C++ (bağlamalar: C#, Lua, Python…)Açık kaynak, nanosaniye çözünürlüklü kare profilleyicisi; çok iş parçacıklı zaman çizelgesi.GitHub sürümü
Unity Entities · Jobs · BurstUnityECS, çok çekirdekli işler, yüksek performanslı derleyici.Package Manager
Unreal MassUnreal 5Binlerce varlık için veri odaklı kalabalık/trafik çerçevesi (MassEntity, MassAI).Plugins → MassEntity, MassAI

🧩 YZ performansını yönetmek

  1. Bütçe yazın: “YZ ≤ 3 ms, yol bulma ≤ 1 ms, algılama ≤ 1 ms” gibi; hedef cihazda.
  2. İşaretleyin ve sayın: her alt sistem için profil işaretçisi ve sayaç (ışın, düğüm, aktif ajan).
  3. En kötü durumu test edin: “en kalabalık sahne” test seviyesi; otomatik performans testi (gerileme alarmı).
  4. Önce algoritma: O(n²) → ızgara; her kare → olay; tekrar → önbellek. Sonra kademelendirme ve LOD. En son mikro optimizasyon ve iş parçacıkları.
  5. Gecikmeyi gizleyin: kuyrukta bekleyen NPC kaba bir tepki versin.
  6. Hata ayıklama görünümü: hangi NPC hangi LOD’da, kaç karedir güncellenmedi: oyun içinde renkli gösterin.
Sık hatalar
  • Editörde ölçüp oyuncu cihazını unutmak.
  • Ortalama FPS’ye bakıp sıçramaları kaçırmak.
  • Unity’de her NPC’ye ayrı Update, her karede GetComponent, LINQ ve çöp üreten kod.
  • Optimizasyonun davranışı bozduğunu fark etmemek (LOD’da duvara takılan uzak NPC): görsel test şart.
⚙️ Mobil ve webDaha az çekirdek, ısınma ve pil: bütçeler masaüstünün yarısı ya da daha azı. WebGL’de iş parçacıkları sınırlıdır.

🤖 Bu konuyu bir YZ kod asistanıyla yazarken

Sık yapılan hatalar — kontrol edin
  • Ölçmeden “bu yavaş olabilir” diye kodu karmaşıklaştırmak
  • Asistanın önerdiği iş parçacığı kodunu yarış durumu açısından incelemeden kullanmak
  • Her karede new ile nesne üretmek (çöp toplayıcı takılmaları)
  • Davranışı bozan agresif LOD’u test etmeden yayına koymak
İyi bir istek (prompt) örneği

“Unity 6, C#. Bir AIScheduler yaz: (1) IAIAgent arayüzü (Think(), DistanceToPlayer, IsVisible, IsPlayerTarget). (2) Her kare 2 ms bütçe (Stopwatch). (3) Öncelik: oyuncunun hedefi ve 15 m içindekiler her kare; görünür olanlar en fazla 5 karede bir; görünmeyenler en fazla 30 karede bir; kalan bütçe en uzun süredir güncellenmeyene. (4) ProfilerMarker ile “AI.Think” ölçümü ve kare başına güncellenen ajan sayısını Profiler Counter olarak yayınla. (5) Sahne görünümünde her ajanın üstünde son güncellemeden bu yana geçen kare sayısını renkli gösteren Gizmos. (6) 1000 ajanla en kötü durum performans testi (PlayMode test).”

  • Önce profil sonucunu (hangi fonksiyon, kaç ms) asistana verin, sonra optimizasyon isteyin
  • Optimizasyondan önce/sonra ölçen bir test isteyin
  • İş parçacığı kodunda veri sahipliğini açıkça sorun
  • Hata ayıklama görselleştirmesi (LOD renkleri, bekleme süresi) isteyin

🔬 Araştırma ucu

Dikkat tabanlı LODGöz izleme ve oyuncu modeliyle (Y17) “oyuncu neye bakıyor?” tahmini; LOD Trader’ın kritiklik modellerini öğrenerek ayarlamak.
GPU’da YZAkış alanları, etki haritaları, binlerce ajanın steering’i GPU hesaplamasıyla (compute shader); Game AI Pro’in “Introduction to GPGPU for AI” bölümü.
Sinir ağı çıkarım maliyetiY13/Y16’daki öğrenilmiş modelleri oyunda çalıştırmak: model küçültme (nicemleme), toplu çıkarım, Inference Engine ile GPU/CPU seçimi.

💬 Tartışma soruları

Yanınızdakiyle 2 dakika konuşun, sonra sınıfça tartışalım
  1. Oynadığınız bir açık dünya oyununda uzaktaki NPC’lerin “tuhaf” davrandığını (yerinde sayan, birden beliren, duvara yürüyen) gördünüz mü? Şimdi bunun sebebini tahmin edebilir misiniz?
  2. Ortalama 60 FPS ama saniyede bir takılan oyun mu, sabit 40 FPS oyun mu? Hangisini oynamak istersiniz, neden? Peki bir dövüş oyununda? Bir strateji oyununda?
  3. Cities: Skylines II’de internet “dişleri” suçladı; asıl sebep başkaydı. Bir oyunun yavaşlığı hakkında okuduğunuz bir iddiayı nasıl doğrulardınız?
  4. Assassin’s Creed Unity’de 10.000 kişilik kalabalığın yalnızca 40’ı “gerçekten düşünüyor”. Bu bir hile mi? Oyuncu fark etmiyorsa NPC’nin düşünüp düşünmemesi önemli mi?
  5. Dönem projenizde hangi YZ sistemi en pahalı olacak? Onu ölçmeden optimize etmeye başlasanız en büyük risk ne olur?

🚀 Proje ve araştırma önerileri

  1. [kolay] Profil raporu — Önceki haftalardan bir demonuzu (ör. boids, A*) profilleyip en pahalı 3 fonksiyonu ve bir iyileştirmeyi önce/sonra ölçümleriyle raporlayın.
  2. [kolay] Kademeli algılama — 200 nöbetçi: görüş ışınlarını her kare yerine kademeli yapın; kare süresi ve tepki gecikmesi grafiği.
  3. [orta] Yol isteği kuyruğu — Unity’de A* (ya da NavMesh) isteklerini kuyruklayan, kare başına bütçeli bir PathService; 100 NPC aynı anda istediğinde sıçrama olmasın.
  4. [orta] Kalabalık havuzu — AC Unity fikri: 2000 ucuz “figüran” + 30 tam YZ havuzu; oyuncuya yaklaşanlar fark ettirmeden tam YZ’ye geçsin.
  5. [zor] Jobs ile boids — Y7’deki boids’i Unity Jobs + Burst + uzaysal ızgarayla 10.000 ajana çıkarın; ölçüm tablosu.
  6. [araştırma] LOD algı deneyi — Aynı sahnenin uzaklık tabanlı ve öncelikli LOD sürümlerini videoya alıp izleyicilere “bir terslik fark ettiniz mi?” diye sorun (Sunshine-Hill’in deneyinin küçük bir tekrarı).

Neler öğrendik? 🎒

  • Bütçe: 60 FPS = 16,7 ms; YZ birkaç ms; en kötü kare önemlidir.
  • Önce ölç: profilleyici, işaretçiler, sayaçlar; Cities: Skylines II’nin diş efsanesi.
  • Zaman dilimleme ve kuyruklar: işi karelere yay, açlığa dikkat.
  • YZ LOD’u: uzaklık değil fark edilme (LOD Trader); havuzlama (AC Unity).
  • Olay tabanlı güncelleme, önbellek, ön hesaplama, uzaysal yapılar.
  • Veri odaklı tasarım: SoA, Unity DOTS, Unreal Mass; iş parçacığı güvenliği.
  • Sıra: algoritma → kademelendirme/LOD → mikro optimizasyon.
  • Sonraki ve son: proje: bütün dönemi tek bir oyunda birleştirmek.

🎮 Bu sunumdaki oyunlar

Adı geçen oyunu tanımıyorsanız: oyuncuların kullandığı wiki sayfası ve oyunu kısaca gösteren bir video. ▶ video slaydın üstünde açılır (Esc ile kapanır); 🎯 işaretli bağlantılar doğrudan bu sunumdaki konuya gider.

Final Fantasy XV 2016 · aksiyon RPG
Dört arkadaşın yol hikâyesi; yoldaşlar FSM + davranış ağacı karışımı bir YZ ile savaşır.
Cities: Skylines II 2023 · şehir kurma
Trafiği, ekonomisi ve vatandaşları simüle edilen şehir kurma oyunu; çıkışta performans sorunları yaşadı.
Assassin’s Creed Unity 2014 · açık dünya aksiyon
Fransız Devrimi Paris’inde geçen, dev kalabalıklarıyla bilinen oyun.
Fieldrunners 2 2012 · kule savunma
Binlerce birimin haritayı geçmeye çalıştığı mobil kule savunma oyunu; hepsi tek bir akış alanını okur.

Kaynaklar: videolar 🎬

📄 Akademik okumalar

Sunshine-Hill 2013 · Phenomenal AI Level-of-Detail Control with the LOD Trader (Game AI Pro, Bölüm 14)
Fark edilme olasılığına dayalı LOD.
Graham 2021 · Efficient, Event-Based Simulations (Game AI Pro Online, Bölüm 2)
Zaman dilimleme ve olay tabanlı güncelleme.
Pentheny 2013 · Efficient Crowd Simulation for Mobile Games (Game AI Pro, Bölüm 24)
Fieldrunners 2 akış alanları.
Johnson ve ark. 2017 · Logging Visualization in FINAL FANTASY XV (Game AI Pro 3, Bölüm 3)
Kayıt + görselleştirme ile hata bulma.
Skarupke 2021 · Automated AI Testing: Simple tests will save you time (Game AI Pro Online, Bölüm 1)
YZ için otomatik testler.

Kaynaklar: hikâyelerin izi 📰

FINAL LEVEL ▶
Proje: Hepsini Birleştir
Dönem projesi, mimari, değerlendirme
SONRAKİ SUNUM ▶