leonscottkfm

Unreal MVP
31 May 2015
1,542
5
219
63
28
(34) İstanbul Avrupa
store.steampowered.com
Şimdi 6 yıldır Unreal ile uğraşıyorum fakat Event Dispatcherlerin ne olduğunu hala çözemedim ve kullanmıyorum da.
Daha doğrusu kullanma gereği duymuyorum.Sanki çok gereksiz küçük bir şeymiş gibi geliyor.Bugüne kadar yaptığım tüm projelerde Custom Event ile her işimi hallettim diyebilirim. Fonksiyonları bile neredeyse çok az kullanıyorum.Çünkü Custom Event bir fonksiyonun yapacağı işi de yapabiliyor.Hadi fonksiyonları anlarım çıkışları bulunmakta.Bu çıkışlar sayesinde değer kontrolü yapıp o değer ile başka olaylar gerçekleştirebilmemizi sağlar. Fakat Event Dispatcher tam olarak ne işe yarıyor ? Bana daha önce Event Dispatcher ile ilgili bir örnek verilmişti.


Mesela bir npc öldüğünde kapı açılsın gibi şeyler de yapılıyor. İyi de ben 2 custom event oluştursam, biri kapı açma diğeri canavarın ölümünü kontrol etme olsa. Gerçi bu tek event ile de yapılır. Her neyse daha sonra o custom eventi çağırırım ve kapı açılır. Event Dispatcher ile neden yolu uzatayım ki?
 
Merhabalar,
 Burada Event Dispatcher ların UE içinde nasıl uygulandıklarını anlatmayacağım. Bu konuda internette bir çok ders tutorial mevcut. Ben sadece neden kullanmanız gerektiğini anlatacağım. Bunun için 2 genel sebep var. Birisi optimizasyon, Diğeri ise haber yayımı (Benim deyimimle). Önce mantığını anlatacağım sonra bu iki sebebi örneklerle açıklamaya çalışacağım:
 
 Mantığı:
 Dispatcher ingilizcede telsiz anlamında kullanılır. Mesela polisler telsize "Dispatcher" derler ve şöyle kullanırlar: Bir polis amiri ya da her hangi bir polis telsizden yayın yapar "Şu şu mahallede hırsız görüldü şu an peşindeyiz tüm birimlerin dikkatine". Bunu duyan bütün polisler duyar duymaz ellerinde ki işi bırakır ve o hırsıza yönelirler. Bu sırada merkezde santral deki polis belki daha üst amirlere haber ulaştırırken o da kaymakam muhtar falan onları arar. Bu sırada bunu duyan trafik polisi ise yolları kesmeyi düşünebilir. Gece bekçileri ise o mahalledeki bekçi sayısını derhal arttırabilir. Bütün bu işler nasıl başladı, bir polis memurunun bir telsiz çağrısı ile. Bu arada telsiz tüm herkese haber vermek için kullanıldığı gibi sadece iki polis arasında da haberleşme amacı ile kullanılabilir. Mesela bir polis diğerine benim yanıma gelir misin diyebilir. İşte UE Event Dispatcher aynen budur. Bütün o referanslarla ulaşmaya çalıştığınız değişken tuttuğunuz sistemleri kenara koyup oyun içerisindeki bir obje den diğerine telsiz çağrısı yapsam o da ne yapması gerekiyorsa onu yapsa olmazmı diye düşünseniz. Bir polisin çağrı yaptığı gibi mesela oyundaki karakterimiz bir çağrı yapsa ve bu çağrı oyundaki tüm widgetlara hatta diğer nesnelere de ulaşsa, ve tüm bu  kendilerine düşen işi otomatik yapsalar olmazmıydı. Event Dispatcher aynen budur. Şimdi örnek verelim.

 1. Optimizasyon:
  Mesela Call of Duty gibi bir oyun yapsaydınız ve ana karakterinizin bir HealthBar yani bir can göstergesi olsaydı: Muhtemelen UMG widget ta bir progressbar yapardınız ve karakterin health (Can) değerini buraya bağlardınız değil mi? Even en basit çözüm yolu böyledir ancak bu normalde yüklenmesi gereken CPU yüküne göre belki 200 kattan daha fazla iş yükü getirecektir. Çünkü widget ı karakterin health değişkenine bağladığınızda diyorsunuz ki: " Her saniye de 1000 defa Health(Can)  değerini kontrol et ve buradaki widgetın değerini güncelle". Bu aynen yukarıdaki analojide şuna benziyor. Bir polis diğer bir polisi saniye başına 1000 defa arıyor ve soruyor "iyi misin?, bir şeyin varmı? bir değişiklik varmı?". Ne kadar büyük bir israf olurdu değil mi. Ama bunu şöyle bir sistem yapsaydık. Karakterimizde bir EventDispatcher (Telsiz)  olsaydı ve bizim widget ımız kendisini güncelleyen bir fonksiyonu (yani telsiz çağrısı sonucu yapılması gereken işi )  bu Event Dispatcher a bağlasaydı. Karakterimiz sadece kendisine bir darbe geldiğinde EventDispatcher ını ateşleseydi ( Polis diyor ki telsizden "Bana bir darbe geldi") bu otomatik olarak ona bağlı olan tüm fonksiyonları çalıştıracaktı. Dolayısı ile widget fonksiyonu da ona bağlı olduğu için bizim ekrandaki göstergemiz yine olması gerektiği gibi güncellenecekti. 
 Peki iki yöntem arasında ne gibi bir fark var burda. Birinci herkesin bildiği yöntemde saniye de 1000 defa bakmasını istiyoruz o değişkene ve değişken aynı da olsa yine de o göstergeyi güncelliyoruz. Bu büyük bir kaynak israfı. Onun yerine ikinci sistemde eğer karakter 5 dakika boyunca hiç darbe almasa o 5 dakika boyunca o değişken hiç kontrol bile edilmeyecekti. Sadece değerinde bir değişiklik varsa o gösterge güncellenecekti. Saniyede 1000 defa olan bir şeyin 5 dakika da ne kadar boş iş yaptığını siz hesap edin. Peki ya bu hesap işi health yani can hesabı gibi basit bir şey olmasaydı ve biraz daha karmaşık bir hesap kitap gerektirseydi. O zaman saniye de 1000 defa yaptığınız o hesap sonucu değişmese de oyunu durma noktasına getirecekti. O zaman mecbur event dispatcher ları öğrenmek zorunda kalacaktınız.

2. Haber Yayılması:
 Event Dispatcher ların asıl varoluş maksadı ise bu konudur. Burada şöyle bir şey düşünün oyunda bir şey olacak ve oyundaki bir çok nesne buna kendisine uygun şekilde tepki verecek. Yani teknik olarak bir yerde bir Event Dispatcher olacak, diğer tüm istekli nesneler kendilerine uygun bir fonksiyonlarını buna bağlayacaklar. Gerektiğinde Event Dispatcher ateşlenecek ve tüm bu diğer nesneler gereken şeyi yapacaklar. Şimdi örneğe geçelim (örneği anlaşılsın diye extreme veriyorum).
  Bir hayatta kalma türü oyun düşünelim. Oyun da bir anda hava sıcaklığı -40 ın altına düştüğünde oyunun her tarafında bir donma etkisi oluşmasını istiyorsunuz. Şöyleki hava sıcaklığı -40 ın altına düştüğünde, havada uçan kuşlar donarak yere düşsün, etrafta bulunan su birikintileri buza dönüşsün, evlerin saçaklarında buz sarkıtları oluşsun, oyundaki buz dolapları donarak açılamaz hale gelsin, karakterini hızı yavaşlasın ve canı azalmaya başlasın, bu sırada çevrede bulunan diğer karakterler ya da NPC ler yardım istemeye ya da evlerine koşuşmaya başlasınlar, bir kaç tane buz golemi yuvasından çıkıp köylere inip av arasınlar ekrandaki buz göstergesi de dolmaya başlasın falan filan.
  Şimdi bir dakika düşünün bu sistemi en etkin şekilde nasıl yapardınız? (Burda bire bir yani bir NPC öldü kapı açıldı gibi bir ilişki değil 1 e 10000 gibi bir ilişki var)Tüm bu nesnelere birer "Custom Event" verip sonra hepsine sırası ile "Get All Actors of Class" la ulaşıp bir yerden bir döngüye sokup her nesnenin eventini ayrı ayrı çağırır mıydınız ? Peki bir de şu durumu eklesem: Bazı insanlar evlerinde olduğundan bunlardan hiç etkilenmemesi gerekse yani get all actos of class aldığınız ve bulduğunuz tüm karakterlere de bunu uygulamamanız gerekse işler daha da kompleks hale gelmez miydi? Ya siz bu uzun döngüyü çalıştırırken orada olması gereken bir nesne yok olsa, mesela kuş ölmüş olsa oyun çökerdi. Peki sonradan bir başka fonksiyon daha eklemeniz gerekse ya da yeni bir şey yapmanız gerekse. Mesela dışarıda bulunan kedi köpekler donarak ölüyor gibi. Eklemeniz gittikçe bu sistemi daha sıkıntıya sokardı.
  Bunu Event Dispatcher lar ile şöyle çözüyorsunuz. Her nesneye, bu nesnenin cinsi ne olursa olsun bir event yazıyorsunuz ve bu eventi level BP içerisinde tanımlı FrostEventDispatcher isimli event dispatcher a bağlıyorsunuz. Yani her nesne BeginPlay olduğunda bu eventini Level BP de bulunan event dispatcher a bağlıyor.  Yapmanız gereken tek şey level bp de bu FrostDispatcher ı ateşlemek ve unutmak. Oyunda bulunan her nesne kendisine uygun olan işi otomatik yapacaktır. Siz yeni bir şey eklemek istediğiniz de onun bu eventini oraya bağlayabilirsiniz sadece. Dikkat edin. Burada Level BP ateşlediği bu şeylerin ne yaptığından haberi bile yok. Kaç kişinin cevap vereceğinden bile haberi yok. Umurunda değil. O sadece ateşlemeyi yapıyor. Ona bağlanan (Telsize abone olan diyelim polis dilinde) herkes kendiliğinden ne yapması gerektiğini bilecek ve otomatik uygulayacaktır. Mesela burada can barımız göstergemiz aslında bir actor bile değil. Ama o bile ne yapması gerektiğini biliyor ve onu yapıyor. Oyun boyunca "sıcaklık -40 a düşebilir" diye düşünmüyor. Düşerse zaten one level bp haber verecek. Tüm bu nesnelere tick fonksiyonunda hava sıcaklığını kontrol et derseniz oyununuz gereksiz yere performans olarak durma noktasına gelebilir. Bir de her şeyi tick te sürekli kontrol ettirerek kendinize de zulmetmiş olursunuz. Orası öyle kalabalıklaşır ki artık takibi zorlaşır. 
 Yani özetle bir nesne telsiz den yapıyor "Hey benim durum değişti duyanlar tepki göstersin !". O kanala bağlı olan herkes kendi içerisinde ne yapacağını tanımladığı zaman 10 numara sistem işliyor. Bu arada bazı insanlar eve girdiklerinde bu telsizi kapatabilir, çıktıklarında tekrar aça da bilirler. Böylece bu haber geldiğinde onların gereksiz yere heyecan yapmasına da gerek kalmaz. Yani oyunda bir şeyi insan yaptınız diye her durumda tepki vermesi de gerekmez. Sobanın yanına yaklaştığında telsizin o kanalını kapattırırsınız uzaklaştığında açtırırsınız sistem işlemeye devam eder.
Bir nesne kendisine kimin abone olduğunu, kaç abonesi olduğunu,  ya da abone olanların ne yaptığını umursamadan çağrı yapıyor. Her nesne nereye abone olduğunu o abone olduğu yerde başka kaç abone olduğunu diğerlerinin ne yaptığını umursamadan o çağrıya cevap veriyor.
 Umarım biraz açıklayıcı olmuştur.

(Örneği herkes sürekli kullandığı için level bp den haber uçuyor gibi verdim ama siz onu her objeye uygulayabilirsiniz. Meselea karakter bp ya da game mode ya da game instance ya da herhangi bir actor. Ne olursa yani kimin haber uçurduğu hiç te önemli değil. Yani event dispatcher ın nerede tanımlanım nerede ateşlendiği hiç önemli değil. Ayrıca fonksiyon dediğim her yeri custom event olarak anlayabilirsiniz.)
 
Biraz değil bayağı açıklayıcı oldu aslında.Örnekler güzeldi , hikaye okuyormuşum gibi hissettim. Böyle uzunca bir cevap yazıp anlatma isteğini de belirttiğin için teşekkür ederim.
Event Dispatcherler üzerinde biraz çalışırsam nerede nasıl kullanmam gerektiğini anlarım sanırım.
Fonksiyonlar bu kadar önemli değil ama herhalde. Custom Event ile hallediliyor , sadece dönüş almak istediğimde işe yararlar öyle değil mi? Çünkü fonksiyonlarda timer delay gibi şeyler kullanamıyoruz o yüzden kullanmak istemiyorum aslında.Kısıtlı olduklarından.
Forum eskisi gibi aktif değil 2015 ten beri buradayım.Sen bu forumun ilacı gibisin, çöldeki bir su gölü gibi.Senden öğreneceğimiz çok şey var.Forumu aktif olarak kullanıp sürekli sorular sormaya çalışıyorum fakat bunu yaparken örneğin "gta nasıl yaparım" "oyun nasıl yapılır" gibi şeyler değil daha yüzeysel şeyler sorup onları uygulayıp öğreniyorum.
 
Çok teşekkür ederim. Faydalı oluyorsam ne mutlu bana. Maksat faydalı olmak.
  Ben orda hep fonksiyon demişim ama sen hepsini "Custom Event" olarak anla. Öyle dememin sebebi C++ ta her şey fonksiyon ondan dilim alışmış. BP için her fonksiyon dediğim yere sen Custom Event demişim diye düşün. Yani event dispatcher a bağlanacak şeyler fonksiyon değil "custom eventler" zaten.
  Yukarıdaki açıklamayı akılda tutup ingilizce de olsa bir kaç ders izlersen zaten olayı bitirirsin. Uygulaması bu kadar karmaşık değil aslında. Mantığını anlatırken uzun gibi oldu ama sonuçta 3 4 klik te yapılıyor yani.


(Örneği herkes sürekli kullandığı için level bp den haber uçuyor gibi verdim ama siz onu her objeye uygulayabilirsiniz. Meselea karakter bp ya da game mode ya da game instance ya da herhangi bir actor. Ne olursa yani kimin haber uçurduğu hiç te önemli değil. Yani event dispatcher ın nerede tanımlanım nerede ateşlendiği hiç önemli değil)