Varlık Bileşen Sistemi mimari nesnesi tanım gereği mi yönlendiriliyor?


20

Is Varlık Bileşen Sistemi mimarisi nesne tanımı gereği odaklı? Benim için daha prosedürel veya işlevsel görünüyor. Benim düşüncem, bir OO dilinde uygulamanızı engellemediğidir, ancak bunu sağlam bir OO tarzında yapmak deyimsel olmaz.

ECS verileri (E & C) davranıştan (S) ayırıyor gibi görünüyor. Delil olarak :

Fikir, varlığa gömülü hiçbir oyun yönteminin olmamasıdır.

Ve :

Bileşen, belirli bir amaç için gereken minimum veri kümesinden oluşur

Sistemler, belirli bir bileşeni olan bir takım varlıkları alan tek amaçlı işlevlerdir


Bunun nesne yönelimli olmadığını düşünüyorum çünkü nesne yönelimli olmanın büyük bir kısmı verilerinizi ve davranışınızı bir araya getiriyor. Delil olarak :

Buna karşılık, nesne yönelimli yaklaşım, programcıyı, programın geri kalanının doğrudan erişemeyeceği bir yere yerleştirmeye teşvik eder. Bunun yerine, verilerle birlikte verilen ve genellikle yöntem olarak adlandırılan özel olarak yazılmış işlevler çağrılarak verilere erişilir.

Öte yandan ECS, verilerinizi davranışınızdan ayırmakla ilgili gibi görünüyor.

Yanıtlar:


21

Giriş


Varlık bileşen sistemleri, nesne yönelimli bir mimari tekniktir.

Nesneye yönelik programlamayla aynı terimin ne anlama geldiğine dair evrensel bir fikir birliği yoktur. Ancak, varlık-bileşen sistemlerinin özellikle mirasa mimari bir alternatif olarak tasarlandığı açıktır . Kalıtım hiyerarşileri bir nesne neyi ifade etmek için doğal olduğunu , ancak (oyunlar gibi) yazılımının belirli türlü, yerine bir nesne neyi ifade edersiniz yapar .

C ++ veya Java'da çalışmaya alışık olduğunuz “sınıflar ve miras” modelinden farklı bir nesne modelidir. Varlıklar sınıflar kadar etkileyici, tıpkı JavaScript veya Self'deki gibi prototipler gibi - bu sistemlerin hepsi birbirleri açısından uygulanabilir.

 

Örnekler


Hadi diyelim ki Playerbir varlıktır Position, Velocityve KeyboardControlledbariz şeyler bileşenleri.

entity Player:
  Position
  Velocity
  KeyboardControlled

Biliyoruz Positionetkilenen edilmelidir Velocityve Velocitytarafından KeyboardControlled. Soru, bu etkileri nasıl modellemek istediğimizdir.

 

Varlıklar, Bileşenler ve Sistemler


Bileşenlerin birbirlerine referansları olmadığını varsayalım; harici bir Physicssistem tüm Velocitybileşenleri tarar Positionve ilgili varlığın güncellenir ; bir Inputsistem tüm KeyboardControlledbileşenleri tarar ve Velocity.

          Player
         +--------------------+
         | Position           | \
         |                    |  Physics
       / | Velocity           | /
  Input  |                    |
       \ | KeyboardControlled |
         +--------------------+

Bu kriterleri karşılar:

  • İşletme tarafından hiçbir oyun / iş mantığı ifade edilmez.

  • Bileşenler davranışı açıklayan verileri depolar.

Sistemler artık olayları işlemekten ve bileşenler tarafından açıklanan davranışı canlandırmaktan sorumludur . Ayrıca, çarpışmalar gibi varlıklar arasındaki etkileşimlerin ele alınmasından da sorumludurlar.

 

Varlıklar ve Bileşenler


Ancak, bileşenler varsayalım yapmak birbirlerine göndermeler var. Şimdi varlık basitçe bazı bileşenler oluşturan, bunları birbirine bağlayan ve ömürlerini yöneten bir kurucudur:

class Player:
  construct():
    this.p = Position()
    this.v = Velocity(this.p)
    this.c = KeyboardControlled(this.v)

Varlık artık girdi ve güncelleme olaylarını doğrudan bileşenlerine gönderebilir. Velocitygüncellemelere KeyboardControlledyanıt verir ve girdiye yanıt verir. Bu hala kriterlerimizi karşılıyor:

  • İşletme, olayları yalnızca bileşenlere ileten “aptal” bir kaptır.

  • Her bileşen kendi davranışını gerçekleştirir.

Burada bileşen etkileşimleri açıktır, bir sistem tarafından dışarıdan dayatılmamıştır. Bir davranışı tanımlayan veriler (hız miktarı nedir?) Ve onu etkileyen kod (hız nedir?) Birleştirilir, ancak doğal bir şekilde. Veriler davranışın parametreleri olarak görülebilir. Ve bazı bileşenler hiç hareket etmiyor - a bir yerde olmanınPosition davranışı .

Etkileşimler, işletme düzeyinde (“ … Playerile çarpıştığında Enemy” ”) veya tek tek bileşenler düzeyinde (“ … Lifeile bir işletmeyle çarpıştığında Strength”) gerçekleştirilebilir.

 

Bileşenler


İşletmenin var olmasının nedeni nedir? Sadece bir kurucu ise, onu bir bileşen seti döndüren bir işlevle değiştirebiliriz . Daha sonra varlıkları türlerine göre sorgulamak istiyorsak, bunu yapmamızı Tagsağlayan bir bileşene de sahip olabiliriz :

function Player():
  t = Tag("Player")
  p = Position()
  v = Velocity(p)
  c = KeyboardControlled(v)
  return {t, p, v, c}
  • Varlıklar olabildiğince aptaldır - sadece bileşen kümeleridir.

  • Bileşenler olaylara daha önce olduğu gibi doğrudan yanıt verir.

Etkileşimler artık olay türlerini olay türlerinden tamamen ayıran soyut sorgular tarafından ele alınmalıdır . Sorgulanacak başka varlık türü yokTag ; hata ayıklama için isteğe bağlı veriler muhtemelen oyun mantığından daha iyi kullanılır.

 

Sonuç


Varlıklar işlevler, kurallar, aktörler veya veri akışı birleştiricileri değildir. Bunlar isimler modeli beton fenomenler; başka bir deyişle, bunlar nesnelerdir. Wikipedia'nın dediği gibi — varlık-bileşen sistemleri genel nesneleri modellemek için kullanılan bir yazılım mimarisi modelidir.


2
Sınıf tabanlı OO'ya, prototip tabanlı OO'ya ana alternatif, veri ve davranışı birleştiriyor gibi görünüyor. Aslında, sınıf temelli OO kadar ECS'den farklı gibi görünüyor. OO ile ne demek istediğinizi açıklayabilir misiniz?

@ Delnan'ın sorusuna eklemek için, alıntıladığım OO wikipedia makalesinin pasajına katılmıyor musunuz?
Daniel Kaplan

@tieTYT: Wikipedia teklifi kapsülleme ve bilgi gizleme hakkında konuşuyor. Veri-davranış eşleşmesinin gerekli olduğunun kanıtı olduğunu düşünmüyorum, sadece yaygın olduğunu düşünüyorum.
Jon Purdy

@delnan: OO ile hiçbir şey ifade etmiyorum. Benim için nesne yönelimli programlama tam olarak kalayda söylediği şeydir: nesnenin belirli tanımının uygulama tanımlı olduğu “nesnelerle” programlama (işlevler, kurallar, aktörler, veri akışı birleştiricileri vb.) .
Jon Purdy

1
@tieTYT: Sadece vahşi bir ortamda gördüğüm uygulamaları açıklıyordum, bunun geniş bir terim olduğunu söylemek - Vikipedi açıklamasına aykırı değil ama kesinlikle daha geniş.
Jon Purdy

20

YOK HAYIR. Ve kaç kişinin başka türlü oy kullandığına şaşırdım!

paradigma

Bu var Veri Odaklı aka Veriye Dayalı bahsediyoruz çünkü mimarisi ve dil içeri yazıyor. Mimarileri stilleri veya programlama gerçekleşmeleri olan paradigmaların genellikle unadvisably belirli bir dilde çalışılan.


Fonksiyonel?

Senin karşılaştırma Fonksiyonel / Usul programlama alakalı ve anlamlı bir fark var. Ancak, "İşlevsel" bir dilin "Yordamsal" paradigmadan farklı olduğunu unutmayın . Ve yapabilirsiniz gibi bir fonksiyonel dilde ECS uygulamak Haskell insanlar yapmış.


Uyumun gerçekleştiği yer

Gözleminiz alakalı ve yerinde :

“... [ECS] onu bir OO dilinde uygulamanızı engellemiyor, ancak bunu yoğun bir OO şeklinde yapmak deyimsel olmaz”


ECS / ES EC / CE değil

Bileşen tabanlı mimariler, "Entity-Component" ve "Entity-Component-System" arasında bir fark vardır. Bu gelişen bir tasarım deseni olduğu için bu tanımların birbirinin yerine kullanıldığını gördüm. "EC" veya "CE" veya "Varlık Bileşeni" mimarileri bileşenlere davranış getirirken, "ES" veya "ECS" mimarileri sistemlere davranış getirir . Her ikisi de yanıltıcı isimlendirme kullanan ancak genel fikri genel olarak anlayan bazı ECS makaleleri:

Bu terimleri 2015 yılında anlamaya çalışıyorsanız, birinin "Varlık Bileşen Sistemi" ne göndermesinin "Varlık Bileşen mimarisi" anlamına gelmediğinden emin olun.


1
Bu doğru cevap. ECS, OOP paradigmalarına pek uymuyor, çünkü ECS tamamen veri ve davranışı birbirinden ayırırken, OOP ise tam tersi.
Nax 'vi-vim-nvim'

"OOP tam tersi iken" Uygulamada hiç kullanılmayan SmallTalk gibi işe yaramaz akademik tanımlar olmadığı sürece, OOP'nin ne hakkında kabul edilmiş bir tanımı yoktur.
Jean-Michaël Celerier

10

Varlık bileşen sistemleri (ECS'ler), sistemin nasıl tanımlandığına bağlı olarak OOP veya işlevsel bir şekilde programlanabilir.

OOP yolu:

Bir varlığın çeşitli bileşenlerden oluşan bir nesne olduğu oyunlar üzerinde çalıştım. Varlık, tüm bileşenlerinde sırayla güncelleme çağırarak nesneyi yerinde değiştiren bir güncelleme işlevine sahiptir. Bu açıkça OOP tarzıdır - davranış verilerle bağlantılıdır ve veriler değiştirilebilir. Varlıklar yapıcılar / yıkıcılar / güncellemeler içeren nesnelerdir.

Daha işlevsel bir yol:

Bir alternatif varlığın herhangi bir yöntem olmadan veri olmasıdır. Bu varlık kendi başına var olabilir veya basitçe çeşitli bileşenlere bağlı bir kimlik olabilir. Bu şekilde, tamamen işlevsel olmak ve yeni bileşen durumları üreten değişmez varlıklara ve saf sistemlere sahip olmak mümkündür (ancak yaygın olarak yapılmaz).

Görünüşe göre (kişisel deneyimlerden), ikinci yol daha fazla çekiş ve iyi bir sebep kazanıyor. Varlık verilerinin davranıştan ayrılması daha esnek ve yeniden kullanılabilir kod (imo) ile sonuçlanır. Özellikle, bileşenleri / varlıkları toplu olarak güncellemek için sistemleri kullanmak daha performanslı olabilir ve birçok OOP ECS'sini rahatsız eden kurumlar arası mesajlaşma karmaşıklıklarını tamamen önler.

TLDR: Her iki şekilde de yapabilirsiniz, ancak iyi varlık bileşen sistemlerinin faydalarının daha işlevsel niteliklerinden kaynaklandığını iddia ediyorum.


Özellikle bileşenlerin bütün noktası inatçı OOP hiyerarşilerinden uzaklaşmak olduğu için daha fazla çekiş, avantajın iyi açıklaması.
Patrick Hughes

2

Veri Odaklı Varlık Bileşen Sistemleri Nesne Odaklı Paradigmalar ile bir arada bulunabilir: - Bileşen Sistemleri kendilerini polimorfizme borçludur. - Bileşenler hem POD (düz eski veriler) hem de ALSO Nesneleri (Sınıf ve Yöntemlerle) olabilir ve Bileşen Sınıf Yöntemleri'nin yalnızca yerel nesneye ait verileri manipüle etmesi şartıyla, her şey hala 'veri yönelimlidir'.

Bu yolu seçerseniz, Sanal Yöntemleri kullanmaktan kaçınmanızı öneririm, çünkü bunlara sahipseniz, bileşeniniz artık yalnızca bileşen verileri değildir ve bu yöntemlerin daha pahalıya mal olması gerekir - bu COM değildir. Kural olarak bileşen sınıflarınızı harici herhangi bir öğeye yapılan göndermelerden temiz tutun.

Örnek olarak vec2 veya vec3, bu verilere dokunmak için bazı yöntemleri olan bir veri kabı ve daha fazlası verilemez.


2
bu yazıyı okumak oldukça zor (metnin duvarı). Sakıncası var düzenleyebilir daha iyi bir şekle ing? Ayrıca, okuyuculara bağlantılı blog makalesini neden sorulan soru ile yararlı ve alakalı bulabileceklerini açıklarsanız yardımcı olur ...
gnat

... bir şekilde o blogla ilgiliyseniz (siz misiniz?), bağlantıyı açıklamak
gnat

Evet, bu benim blogum, ilgili ve muhtemelen yararlı olduğuna inandığım veri odaklı tasarım ilkelerine dayanan bir nesne odaklı varlık bileşen sisteminin ayrıntılarını açıklayan herkese açık blogumla yakından ilişkiliyim, ancak yine de bağlantıyı kaldırdım önyargıları kaldırın.
Homer

2

ECS'yi temel olarak OOP'tan farklı olarak görüyorum ve bunu, yaptığınız gibi görmeye eğilimliyim, verilerin işlevselden çok farklı bir şekilde ayrılmasıyla, işlevsel veya özellikle prosedürel nitelikte daha yakın. Ayrıca merkezi veri tabanları ile ilgilenen bir tür programlamanın bazı benzerlikleri vardır. Tabii ki resmi tanımlar söz konusu olduğunda en kötü insanım. Kavramsal olarak tanımlandıkları şeyle değil, yalnızca işlerin nasıl olma eğilimiyle ilgiliyim.

Bileşenlerin veri alanlarını topladığı ve herkese açık / küresel olarak erişilebilir olduğu, varlıkların bileşenleri topladığı ve sistemlerin bu veriler üzerinde işlevsellik / davranış sağladığı bir tür ECS varsayıyorum. Bu, tipik olarak nesne yönelimli bir kod tabanı dediğimiz şeyden oldukça zor mimari özelliklere yol açar.

Ve elbette, insanların bir ECS'yi tasarlama / uygulama biçimindeki sınırların bulanıklaşması ve ilk etapta tam olarak bir ECS'yi neyin oluşturduğu hakkında tartışmalar var. Yine de bu tür sınırlar işlevsel veya prosedürel dilde adlandırdığımız kodda bulanıklaştırılmıştır. Tüm bu belirsizlikler arasında, verileri işlevsellikten ayıran bir ECS'nin temel sabiti, işlevsel veya prosedürel programlamaya OOP'tan çok daha yakın görünüyor.

ECS'nin bir OOP sınıfına dahil olduğunu düşünmenin yararlı olmadığını düşündüğüm ana nedenlerden biri, OOP ile ilişkili SE uygulamalarının çoğunun, veri değil, kamu arayüzleri modelleme fonksiyonları ile ortak arayüz kararlılığı etrafında dönmesidir . Temel fikir, kamu bağımlılıklarının büyük kısmının somut verilere değil soyut işlevlere doğru akmasıdır. Bu nedenle, OOP, temel tasarım davranışlarını değiştirmeyi çok maliyetli hale getirirken, somut ayrıntıları (işlevselliği uygulamak için gereken veri ve kod gibi) değiştirmeyi çok ucuz hale getirir.

Kamu bağımlılıklarının büyük kısmı somut verilere: sistemlerden bileşenlere doğru aktıkça, ECS bu konuda radikal olarak farklıdır. Sonuç olarak, ECS ile ilişkili tüm SE uygulamaları veri istikrarı etrafında dönecektir , çünkü en yaygın ve en çok kullanılan arayüzler (bileşenler) aslında sadece veridir.

Sonuç olarak bir ECS, ikisi de radikal olarak farklı işlevselliklerle uygulanmış olsa ve aynı tasarımları paylaşmasa bile, hem DX hem de GL motoruyla aynı tasarımları paylaşmasa bile bir DirectX'in yerine bir OpenGL oluşturma motoru yapmayı kolaylaştırır. aynı kararlı verilere erişebilir. Bu arada çok pahalı olurdu ve örneğin bir a'nın veri sunumunu değiştirmek için bir grup sistemin yeniden yazılmasını gerektirir MotionComponent.

Bu, geleneksel olarak OOP ile ilişkilendirdiğimiz şeyin, en azından birleştirme özellikleri ve "özel uygulama ayrıntıları" ya da "özel uygulama ayrıntıları" nı oluşturan şeylerin tersidir. Tabii ki her iki durumda da "uygulama ayrıntıları" nı değiştirmek kolaydır, ancak ECS'de değiştirilmesi maliyetli olan verilerin tasarımıdır (veriler ECS'de bir uygulama detayı değildir) ve OOP'de değiştirilmesi de maliyetli olan işlevsellik tasarımıdır (fonksiyonların tasarımı OOP'ta bir uygulama detayı değildir). Yani bu "uygulama detayları" için çok farklı bir fikir ve bir bakım perspektifinden bir ECS'nin bana verdiği ana itirazlardan biri, benim alanımda, bir şeyleri yapmak için gereken veriler, bir kez ve herkes için doğru bir şekilde sabitlemek ve tasarlamak için bu verilerle yapabileceğimiz tüm çeşitli şeylerden daha kolaydı (bu, müşteriler zihinlerini değiştirdikçe ve yeni kullanıcı önerileri su bastığında her zaman değişecektir). Sonuç olarak, bağımlılıkları soyut işlevlerden ham, merkezi verilere yönlendirmeye başladığımızda bakım maliyetlerinin düştüğünü fark ettim (ancak yine de, kavramsal olarak tüm verilere rağmen değişmezleri aklı başında tutmaya izin vermek için hangi bileşenlere hangi sistemlere eriştiği konusunda dikkatli olmaktayım. küresel olarak erişilebilir).

Ve en azından benim durumumda, API ile ECS SDK ve tüm bileşenler aslında C'de uygulandı ve OOP'a benzemiyor. ECS mimarilerindeki doğal OO eksikliği ve en geniş dil ve derleyici yelpazesi tarafından kullanılabilecek bir eklenti mimarisine sahip olma arzusu nedeniyle C'yi böyle bir amaç için yeterli buldum . Sistemler hala C ++ 'da uygulanmaktadır, çünkü C ++ işleri çok uygun hale getirir ve sistemler karmaşıklığın büyük bir kısmını modeller ve orada OOP'ye daha yakın kabul edilebilecek birçok şey için kullanım buluyorum, ancak bu uygulama ayrıntıları için. Mimari tasarımın kendisi hala çok prosedürel C'ye benzemektedir.

Bence en azından bir ECS'nin tanımı gereği OO olduğunu söylemeye çalışmak biraz kafa karıştırıcı. En azından temeller, kapsülleme ile başlayarak ve belki de istenen bağlantı özellikleri olarak kabul edilecek şeyle biten, genellikle OOP ile ilişkili temel prensiplerin çoğundan 180 derecelik bir dönüş yapar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.