Bu zor bir soru. Sadece belirli deneyimlerime (YMMV) dayalı bazı soruları çözmeye çalışacağım:
Bileşenler, diğer bileşenlerin verilerine erişmelidir. Örneğin, oluşturma bileşeninin draw yöntemi, dönüştürme bileşeninin konumuna erişmelidir. Bu kod bağımlılıkları oluşturur.
Buradaki bağlantının / bağımlılıkların miktarını ve karmaşıklığını (derecesini değil) küçümsemeyin. Bunun arasındaki farka bakabilirsiniz (ve bu şema oyuncak benzeri seviyelere çok gülünç bir şekilde basitleştirilmiştir ve gerçek dünya örneğinde kuplajı gevşetmek için ara yüzler olacaktır):
... ve bu:
... veya bu:
Bileşenler polimorfik olabilir ve bu da biraz karmaşıklık getirir. Örneğin, oluşturma bileşeninin sanal çizim yöntemini geçersiz kılan bir hareketli grafik oluşturma bileşeni olabilir.
Yani? Bir vtable ve sanal dağıtımın analojik (veya gerçek) eşdeğeri, temel durumunu / verilerini gizleyen nesne yerine sistem üzerinden çağrılabilir. Polimorfizm, analog vtable veya fonksiyon işaretçisi (leri) sistemin çağırması için "veri" türüne dönüştüğünde "saf" ECS uygulaması ile hala çok pratik ve uygulanabilir.
Polimorfik davranış (örneğin renderleme için) bir yere uygulanması gerektiğinden, sadece sistemlere dışarıdan tedarik edilir. (örn. hareketli grafik oluşturma sistemi, oluşturma düğümünü devralan ve oluşturma motoruna ekleyen hareketli grafik oluşturma düğümü oluşturur)
Yani? Umarım bu alaycılık olarak ortaya çıkmaz (sık sık suçlandığım halde niyetim değil ama duyguları metin yoluyla daha iyi iletebilmeyi diliyorum), ancak bu durumda "dış kaynaklı" polimorfik davranış ek bir şekilde ortaya çıkmaz verimlilik maliyeti.
Sistemler arasındaki iletişimi önlemek zor olabilir. Örneğin, çarpışma sistemi, hangi beton render bileşeninden hesaplanmış sınırlayıcı kutuya ihtiyaç duyabilir.
Bu örnek benim için özellikle garip görünüyor. Neden bir oluşturucunun verileri tekrar sahneye çıkardığını bilmiyorum (genellikle bu bağlamda oluşturucuları salt okunur olarak görüyorum) veya bir oluşturucunun bunu hem renderer hem de yapmak için başka bir sistem yerine AABB'leri bulması için çarpışma / fizik (burada "oluşturma bileşeni" adına asılıyor olabilirim). Yine de, bu örnek üzerinde fazlaca asılmak istemiyorum çünkü anlamaya çalıştığınız nokta bu değil. Yine de sistemler arasındaki iletişimin (doğrudan başkaları tarafından yapılan dönüşümlere bağlı sistemlerle merkezi ECS veri tabanına dolaylı okuma / yazma biçiminde bile), gerektiğinde sık sık olması gerekmez. 'O
Sistemin güncelleme işlevlerinin çağrılma sırası tanımlanmamışsa bu durum preformasyonlara neden olabilir.
Bu kesinlikle tanımlanmalıdır. ECS, kod tabanındaki olası her sistemin sistem işleme değerlendirme sırasını yeniden düzenlemek ve çerçeveler ve FPS ile ilgilenen son kullanıcıya tam olarak aynı tür sonuçları almak için son çözüm değildir. Bu, bir ECS tasarlarken, en azından biraz açık bir şekilde öngörülmesini önerdiğim şeylerden biridir (ancak daha sonra aklını değiştirmek için çok fazla bağışlayıcı solunum odası ile, siparişin en kritik yönlerini değiştirmemesi şartıyla) sistem çağırma / değerlendirme).
Bununla birlikte, her çerçevenin tüm yeniden hesaplanması her karenin pahalıdır. Bu nedenle, daha sonra bunları sistemde güncellemek için yapılan tüm değişiklikleri takip etmek için bir listeye ihtiyaç duyulacaktır. OOP yolunda bu, döşeme haritası bileşeni tarafından kapsüllenebilir. Örneğin, SetTile () yöntemi her çağrıldığında köşe dizisini güncelleyecektir.
Veri odaklı bir endişe dışında bunu tam olarak anlamadım. Ve bu tür performans tuzaklarından kaçınmak için, bir ECS'de verileri temsil etme ve kaydetme konusunda herhangi bir tuzak yoktur (ECS'li en büyük olanlar, belirli bileşen türlerinin mevcut örnekleri için sorgulama yapan sistemler gibi genelleştirilmiş bir ECS'yi optimize etmenin en zorlu yönleri). Mantık ve verilerin "saf" bir ECS'de ayrılması, bir OOP temsilinde önbelleğe alabileceğiniz / not edebileceğiniz şeyleri aniden yeniden hesaplamanız gerektiği anlamına gelmez. Ben çok önemli bir şey üzerinde parlama sürece bu bir tartışma / ilgisiz nokta.
"Saf" ECS ile bu verileri döşeme haritası bileşeninde saklayabilirsiniz. Tek büyük fark, bu köşe dizisini güncelleme mantığının bir yerde bir sisteme taşınmasıdır.
Gibi ayrı bir bileşen oluşturursanız, bu önbelleğin geçersiz kılınmasını ve kaldırılmasını basitleştirmek için ECS'ye bile yaslanabilirsiniz TileMapCache
. Bu noktada önbellek istendiğinde ancak bir TileMap
bileşeni olan bir varlıkta kullanılamıyorsa , onu hesaplayabilir ve ekleyebilirsiniz. Geçersiz kılındığında veya artık gerekli olmadığında, bu tür geçersiz kılma ve kaldırma işlemleri için özel olarak daha fazla kod yazmak zorunda kalmadan ECS üzerinden kaldırabilirsiniz.
Bileşenler arasındaki bağımlılıklar, sistemlerde gizlenmesine rağmen hala var
"Saf" bir temsilcideki bileşenler arasında hiçbir bağımlılık yoktur (Bağımlılıkların burada sistemler tarafından gizlendiğini söylemenin oldukça doğru olduğunu düşünmüyorum). Veriler, verilere bağlı değildir. Mantık mantığa bağlıdır. Ve "saf" bir ECS, bir sistemin çalışması için gereken minimum veri ve mantığın (genellikle hiçbiri) mutlak minimal alt kümesine bağlı olacak şekilde mantığın yazılmasını teşvik etme eğilimindedir, bu da genellikle gerçek görev için gerekenden çok daha fazla işlevsellik. Saf ECS'yi doğru kullanıyorsanız, takdir etmeniz gereken ilk şeylerden biri, kapsülleme ve özellikle bilgi gizleme hakkında OOP'de takdir etmeyi öğrendiğiniz her şeyi aynı anda sorgularken ayrılma avantajlarıdır.
Ayrıştırarak özellikle sistemlerinizin ne kadar az bilgiye ihtiyaç duyduğunu kastediyorum. Hareket sisteminizin Particle
veya gibi çok daha karmaşık bir şey hakkında bilgi sahibi olması bile gerekmez Character
(sistemin geliştiricisi sistemde bile var olan bu tür fikirleri bilmek zorunda değildir). Sadece bir yapıda birkaç yüzer gibi basit bir pozisyon bileşeni gibi çıplak minimum verileri bilmek gerekir. Saf bir arayüzün IMotion
onunla birlikte taşıma eğiliminden daha az bilgi ve daha az dış bağımlılık . Öncelikle, her bir sistemin ECS'yi her yerde kademeli arayüz kırılmalarına maruz kalmadan arka plandaki çok beklenmedik tasarım değişikliklerini işlemek için çok affedici hale getirmesi gereken bu minimal bilgi nedeniyle.
Önerdiğiniz "saf olmayan" yaklaşım, şu anda mantığınız kesinlikle değişikliklerin kademeli kırılmalara neden olmadığı sistemlerde yerelleştirilmediğinden, bu faydayı bir miktar azalttığını öneriyoruz. Mantık şimdi, onu kullanabilen tüm çeşitli sistemlerin arayüz gereksinimlerini karşılamak zorunda olan çoklu sistemlerin eriştiği bileşenlerde bir dereceye kadar merkezileştirilecek ve şimdi her sistemin daha fazla bilgiye sahip olması (buna bağlı) olması gerektiği gibi bu bileşenle çalışılması gerekenden daha fazla bilgi.
Verilere Bağımlılıklar
ECS hakkında tartışmalı olan şeylerden biri, soyut arayüzlere olan bağımlılıkları olabilecekleri sadece ham verilerle değiştirme eğiliminde olmasıdır ve bu genellikle daha az arzu edilen ve daha sıkı bir bağlantı şekli olarak kabul edilir. Ancak, ECS'nin çok faydalı olabileceği oyunlar gibi alan adlarında, veri sunumunu önceden tasarlamak ve sabit tutmak, sistemin bazı merkezi seviyelerinde bu verilerle yapabileceklerinizi tasarlamaktan daha kolaydır. Bu, kod tabanlarındaki tecrübeli gaziler arasında bile, benzer şeylerle daha fazla COM tarzı saf arayüz yaklaşımı kullanan acı verici bir şekilde gözlemlediğim bir şey IMotion
.
Geliştiriciler, bu merkezi arayüze işlev eklemek, kaldırmak veya değiştirmek için nedenler bulmaya devam ettiler ve her değişiklik korkunç ve maliyetliydi çünkü IMotion
kullanılan sistemdeki her yerle birlikte uygulanan her bir sınıfı kırma eğilimi gösterecekti IMotion
. Bu arada çok acı verici ve basamaklı değişikliklerle tüm zaman boyunca, uygulanan nesnelerin IMotion
hepsi sadece 4x4 şamandıra matrisini depolamaktaydı ve tüm arayüz sadece bu şamandıraların nasıl dönüştürüleceği ve erişileceği ile ilgiliydi; veri gösterimi baştan beri istikrarlıydı ve beklenmedik tasarım ihtiyaçları ile değişmeye eğilimli olan bu merkezi arayüz ilk etapta bile olmasaydı çok fazla acıdan kaçınılabilirdi.
Bu, küresel değişkenler gibi neredeyse iğrenç gelebilir, ancak ECS'nin bu verileri sistemler yoluyla tür tarafından açıkça alınan bileşenlere nasıl organize ettiği, bunu derlerken, derleyiciler bilgi gizleme, erişen ve mutasyona uğrayan yerler gibi bir şeyi zorlayamaz. veriler genellikle değişmezleri etkili bir şekilde sürdürmek ve bir sistemden diğerine ne tür dönüşümlerin ve yan etkilerin devam ettiğini tahmin etmek için yeterince açık ve açıktır (aslında, belirli alanlarda OOP'den tartışmasız daha basit ve daha öngörülebilir olabilecek şekillerde) sistem düz bir boru hattına dönüşür).
Son olarak, saf bir ECS'de animasyonu nasıl ele alacağım sorusunu sormak istiyorum. Şu anda bir animasyonu, 0 ile 1 arasındaki bazı ilerlemelere dayanarak bir varlığı manipüle eden bir functor olarak tanımladım. Animasyon bileşeni, animasyonlar listesine sahip animatörlerin bir listesine sahiptir. Güncelleme fonksiyonunda, o anda aktif olan animasyonları varlık için uygular.
Hepimiz burada pragmatistiz. Gamedev'de bile muhtemelen çelişkili fikirler / cevaplar alırsınız. En saf ECS bile, insanların kedilerin nasıl ciltleneceği konusunda en güçlü fikirleri formüle etmediği nispeten yeni bir fenomen, öncü bir bölgedir. Bağırsak reaksiyonum, oluşturma sisteminin görüntülenmesi için animasyonlu bileşenlerde bu tür animasyon ilerlemesini arttıran bir animasyon sistemidir, ancak bu, belirli uygulama ve bağlam için çok fazla nüansı göz ardı eder.
ECS ile gümüş bir mermi değil ve kendimi hala içeri girip yeni sistemler ekleme, bazılarını kaldırma, yeni bileşenler ekleme, mevcut yeni bir sistem türünü almak için mevcut bir sistemi değiştirme vb.Gibi eğilimlerle buluyorum. ilk seferinde her şey yolunda. Ancak benim durumumdaki fark, belirli tasarım ihtiyaçlarını önceden tahmin edemediğimde merkezi bir şeyi değiştirmemem. Her yere gitmemi ve ekilen bazı yeni ihtiyaçları karşılamak için çok fazla kod değiştirmemi gerektiren basamaklı kopmaların dalgalanma etkisini almıyorum ve bu oldukça zaman tasarrufu. Ayrıca beynimde daha kolay buluyorum çünkü belirli bir sistemle oturduğumda, üzerinde çalışmak için ilgili bileşenlerin (sadece veri olan) dışında başka bir şey hakkında çok fazla şey bilmem / hatırlamam gerekmiyor.