Bir varlık bileşen sisteminde “Blob-Systems” nasıl önlenir?


10

Şu anda aşağıdaki sorunla karşı karşıyayım:

Bir varlık bileşen sistemi (ECS) kullanarak bir pong klonu yazmaya çalışıyorum . "Çerçeveyi" tek başıma yazdım. Yani varlıkları tüm bileşenlerle yöneten bir sınıf var. Sonra bileşen sınıfları kendileri var. Son olarak, sistemin ihtiyaç duyduğu bileşenlere sahip tüm varlıkları elde eden sistemlerim var.

Örneğin, benim hareket sistemim bir pozisyon bileşeni ve bir hareket bileşeni olan tüm varlıkları arar. Konum bileşeni sadece konumu ve hareket bileşeni hızı tutar.

Ama asıl sorun çarpışma sistemim. Bu sınıf mantıklı bir damla gibidir. Bu sınıfta çok özel durumlarım var.

Örneğin: Küreklerim kenarlıklarla çarpışabilir. Bu durumda hızları sıfıra ayarlanır. Topum da sınırlarla çarpışabilir. Ancak bu durumda hızı sınırın normalinde yansıtılır, böylece yansıtılır. Bunu yapmak için topa ekstra bir fizik bileşeni verdim: "Hey, bu şey durmuyor, yansıtıyor." Aslında fizik bileşeninin gerçek bir verisi yoktur. Sisteme bir nesnenin yansıtıp yansıtmadığını veya durup durmadığını söylemek için boş bir sınıftır.

Sonra geliyor: Top kürekler veya sınırlarla çarpıştığında bazı parçacıklar oluşturmak istiyorum. Bu yüzden topun çarpışma sistemine çarpışmada parçacık yaratmasını söyleyen başka bir bileşen alması gerektiğini düşünüyorum.
Sonra kürekler ile çarpışabilir ancak sınırları ile değil güç ups istiyorum. Bu durumda, güçlendiriciler yok olmalıdır. Bu yüzden çok daha fazla vakaya ve bileşene ihtiyacım olacaktı (sisteme bazı varlıkların sadece diğerleriyle çarpışabileceğini söylemek için, bazıları gerçekten çarpışabiliyor olsa bile, herkesle çarpışmayacak, ayrıca çarpışma sistemi kürekler, vb.).

Varlık bileşen sisteminin iyi bir şey olduğunu görüyorum çünkü esnek ve kalıtımla ilgili sorunlarınız yok. Ama şu anda tamamen takılıp kaldım.

Çok karmaşık mı düşünüyorum? Bu sorunla nasıl başa çıkmalıyım?

Tabii, aslında "çarpışma sonrası" ndan sorumlu sistemler yaratmak zorundayım, bu yüzden çarpışma sistemi sadece "Evet, son karede bir çarpışma var" der ve sonra bir sürü "çarpışma sonrası" sistem vardır. hepsi farklı (kombinasyonları) bileşenler gerektirir ve daha sonra bileşenleri değiştirir. Örneğin, çarpışma anında durması gereken şeyleri durduran bir çarpışma sonrası hareket sistemi olurdu. Sonra bir şeyleri yansıtan bir çarpışma sonrası sistem.

Ama bu benim için de uygun bir çözüm gibi görünmüyor, çünkü:

  1. Hareket çarpışma sonrası sistemim, bir konum bileşeni, bir hareket bileşeni ve çarpışma bileşenine sahip varlıklara ihtiyaç duyacaktır. Ardından, varlığın hızını sıfıra ayarlayacaktır.
  2. Çarpışma sonrası fizik sisteminin bir pozisyon bileşeni, bir hareket bileşeni, bir çarpışma bileşeni ve bir fizik bileşeni olan varlıklara ihtiyacı olacaktır. Sonra hız vektörünü yansıtır.

Sorun açıktır: Çarpışma sonrası hareket, fizik çarpışma sonrası sistemdeki varlıkların bir alt kümesi olan varlıklara ihtiyaç duyar. Dolayısıyla çarpışma sonrası iki sistem aynı veriler üzerinde çalışacaktı, etki şu: Bir işletmenin fizik bileşeni olmasına rağmen, bir çarpışmadan sonra hız sıfır olacaktır.

Bu sorunlar genel olarak bir varlık bileşen sisteminde nasıl çözülür? Bu problemler normal mi yoksa yanlış bir şey mi yapıyorum? Evetse, bunun yerine ne ve nasıl yapılmalıdır?

Yanıtlar:


11

Evet, çok karmaşık düşünüyorsun.

Bir çok mesajlaşma sistemi ve bazı filtreleri belirtmenize izin veren bazı ek özellikler ile çözülebilecek gibi görünüyor ve nihayet varlıklar / bileşenlerle bu kadar katı olmaktan endişe etmiyorsunuz.

Mesajlaşma, parçacıkları tetikleme, powerups ve benzeri gibi bazı konularda size yardımcı olacaktır. Örneğin, parçacık olaylarına abone olan ve olayda açıklanan konumda parçacıklar oluşturan bir dünya nesneniz olabilir.

Filtreler çarpışmalarda size çok yardımcı olacaktır. Filtreler, bir nesnenin bir başkasıyla çarpışıp çarpışmadığını ve hangi yanıta sahip olacağını tanımlayabilir. Fizik bileşeninize, ne tür bir fizik bedeninin olduğunu, başka hangi fizik bedenleriyle çarpıştığını ve cevabın ne olması gerektiğini tanımlayan bazı özellikler eklersiniz. Örneğin, bir top fiziği nesnesi bir kürek fiziği nesnesiyle çarpışır ve yansıma ve parçacıklar ile tepki verir.

Son olarak, uygulamanız konusunda çok katı olmayın. Çalışmasını sağlamak için bir yol bulabilirseniz, ancak gerçekten EC sistemi değilse, yapın. Yukarıdaki örneğimde olduğu gibi, partiküllerin bir sistem veya EC sisteminin bir parçası tarafından yönetilmesine gerek yoktur. Oyunu bitirmek, zaten oldukça zayıf bir şekilde tanımlanmış bir yöntemi kesinlikle uygulamaktan daha önemlidir.


Çok teşekkür ederim. Sadece nasıl ölçeklendiğine bakmak için bir ECS kullanarak bir oyun oluşturmak istedim ve makalelerde ve derslerde okuduğumda kullanmak gerçekten çok güzel. Benim sorunum şuydu: "Şimdi bir ECS'm var ve her şey bununla yönetilmeli." Ben de ECS ile bağlantılı olarak parçacık sistemini yazmayı planladım. Ayrıca, bazı makalelerde her bileşenin gerçekten sadece bazı temel verilere sahip olması ve başka bir şey olmaması gerektiğini okudum. Bu genellikle benim sorunum ... Sanırım çok karmaşık.
M0rgenstern

Sadece nasıl ölçeklendiğine bakmak için bir ECS kullanarak bir oyun oluşturmak istedim ve makalelerde ve derslerde okuduğumda kullanmak gerçekten çok güzel . Hedefiniz buysa, kendi bileşeninizi oluşturmak yerine mevcut Bileşen / Varlık sistemlerine bakmanızı öneririm. Muhtemelen "alabildiği kadar saf Bileşenler" olan Unity3D'yi indirin ve orada oynayın. Çok daha hızlı öngörüler, IMHO.
Imi

3
@lmi: Unity, bileşen tabanlı olmasına rağmen bir Varlık Bileşen Sistemi değildir. ECS, basitçe oyun nesnesi bileşenlerine sahip olmaktan ve kullanmaktan daha katı kurallara sahiptir ( asla bir modeli kural olarak düşünmeyin). Bir dizi makale nedeniyle ECS şu anda oyun geliştiricilerin bazı bölümlerinde popülerdir, bu nedenle ECS ile ilgili olarak genel olarak bileşen tabanlı tasarım yerine birçok soru vardır.
Sean Middleditch

12

Çok karmaşık şeylersiniz. Bileşen tabanlı tasarım kullanmanın bile bu kadar basit bir oyun için aşırı derecede ağır olduğunu söyleyecek kadar ileri giderdim. Oyununuzu hızlı ve kolay bir şekilde geliştiren şeyleri yapın. Bileşenler, çok çeşitli davranışlara ve oyun nesnesi yapılandırmalarına sahip daha büyük projelerde yinelemeye yardımcı olur, ancak böyle basit bir iyi tanımlanmış oyuna faydaları daha tartışmalıdır. Geçen yıl bunun hakkında bir konuşma yaptım: bir mimariye bağlı kalmak yerine bir oyun yapmaya odaklanırsanız birkaç saat içinde eğlenceli küçük oyunlar oluşturabilirsiniz . 100 veya 20 farklı nesne türünüz olduğunda kalıtım bozulur, ancak yalnızca bir avuç içiniz varsa işe yarar.

Bileşenleri öğrenme amacıyla kullanmaya devam etmek istediğinizi varsayarsak, yaklaşımınızda göze çarpan bazı belirgin sorunlar vardır.

İlk olarak, bileşenlerinizi bu kadar küçük yapmayın. 'Hareket' gibi ince taneli bileşenlere sahip olmanız için hiçbir neden yoktur. Oyununuzda jenerik bir hareket yok. Hareketi giriş veya AI ile sıkıca bağlı olan kürekleriniz var (ve gerçekten hız, ivme, restitüsyon vb. Kullanmıyorlar) ve iyi tanımlanmış bir hareket algoritmasına sahip olan topunuz var. Bir PaddleController bileşenine ve BouncingBall bileşenine veya bu satırlar boyunca bir şeye sahip olmanız yeterlidir. Daha karmaşık bir oyun alırsanız / alırsanız, daha genel bir PhysicsBody bileşenine sahip olmaktan endişe edebilirsiniz ('gerçek' motorlarda temel olarak oyun nesnesi ile Havok / PhysX / Bullet / Box2D / etc.) Çok daha çeşitli durumları ele alır.

Bir 'pozisyon' bileşeni bile şüphesiz nadir değildir. Fizik motorları tipik olarak bir nesnenin nerede olduğu konusunda kendi iç fikirlerine sahiptir, grafiklerin enterpolasyonlu bir temsili olabilir ve AI aynı verilerin farklı bir durumda başka bir temsiline sahip olabilir. Her sistemin, sistemin kendi bileşenlerindeki dönüşüm konusundaki kendi fikrini yönetmesine izin vermek ve daha sonra sistem arasında düzgün bir iletişim olmasını sağlamak avantajlı olabilir. Etkinlik akışlarıyla ilgili BitSquid blog yayınına bakın .

Özel fizik motorları için, bileşenleriniz hakkında veri sahibi olmanıza izin verildiğini unutmayın. Genel bir Pong fizik bileşeni, hangi eksenlerde hareket edebileceğini gösteren verilere sahiptir (örneğin, vec2(0,1)sadece Y ekseninde hareket edebilen kürekler için bir çarpan olarak, ancak hareket vec2(1,1)edebileceğini gösteren top için), bir işaret veya şamandıra top tipik olarak 1.0ve kürekler0.0), ivme özellikleri, hız, vb. Yüksek oranda ilişkili her veri parçası için bunu bir bazilyon farklı mikro bileşene ayırmaya çalışmak, ECS'nin başlangıçta yapması gereken şeylerin tersidir. Mümkün olduğunca aynı bileşende birlikte kullanılan şeyleri saklayın ve yalnızca her oyun nesnesinin bu verileri kullanma biçiminde büyük bir fark olduğunda bölün. Pong için top ve kürekler arasındaki fiziğin ayrı bileşenler olacak kadar farklı olmasını sağlamak için bir argüman var, ancak daha büyük bir oyun için, 1-3'te iyi çalışan şeyleri yapmak için 20 bileşen yapmaya çalışmak için çok az neden var.

ECS sürümünüz yoluna girerse / girerse, oyununuzu gerçekten yapmak için gerekenleri yapın ve bir tasarım desenine / mimarisine bağlı kalmayı unutun.


1
Gerçekten teşekkür ederim! ECS'nin pong gibi küçük bir oyun için çok iyi ölçeklenmediğini biliyorum. Ama sadece böyle bir şeyin gerçekte nasıl uygulandığını ve nasıl çalıştığını görmek için kullandım. Bileşenleri çok küçük yaptım, çünkü bazı makalelerde çoğunlukla okuduğum buydu. Birçok bileşene sahip olmak ve her bileşen yalnızca temel verileri içerir. Peki, seni mi anlıyorum, miras ve ECS arasında bir karışım kullanmanızı önerir misin? Dediğiniz gibi "top ve kürekler ayrı bileşenler olacak kadar farklı". Örneğin, onlara hem bir Hareket / Pozisyon bileşeni (belki de bir bileşen olarak) hem de
M0rgenstern

1
Nasıl uygun görürsen. Oyunu yapmaya odaklanın. Kelimenin tam anlamıyla Ball, hareket, zıplama vb.Gibi topun tüm mantığını içeren bir Paddlebileşene ve girdi alan bir bileşene sahip olacaktım, ama bu benim. Size en mantıklı olan ve yolunuzdan çıkan ve oyunu yapmanıza izin veren şey, bir şeyler yapmanın "doğru yolu" dur.
Sean Middleditch

3
Kelimenin tam anlamıyla, top için hareket, zıplama vb.Gibi tüm mantığı içeren Ball adlı bir bileşene ve girdi alan bir Paddle bileşenine sahip olacaktım, ama bu benim. Bu yüzden her programcı için "bileşen sisteminin ne olduğu" hakkında bir görüş vardır. Ben tavsiye DEĞİL tamamen klasik Varlık sistemlerinde düşündüğünü ve Komponent sistemi kullanmak zorunda kalıyor dışında bu öneri gibi yapmak ama farklılıklar aslında ne bakmak istemiyorum.
Imi

2
@lmi: bileşenleri olan birkaç büyük oyun / motor üzerinde çalıştı ve neden bileşenleri kullandığımızı ilk elden gördüğümüzde, hayır, aşırı taneli bileşenler değerinden daha fazla sorun değil. Bileşenler sihirli bir kurşun değildir; bir oyun geliştiricisinin araç kutusundaki birçok araçtan biridir. Onları sisteme daha fazla zihinsel ve çalışma zamanı yükü ekledikleri şekilde değil, yardım ettikleri bir şekilde kullanın. Top fiziğine sahip tek şey topsa, diğer top özelliklerinden ayırmanın sıfır avantajı vardır . Bu değişirse ve değiştiğinde, yalnızca ve sonra bölün.
Sean Middleditch

1
Pragmatik olma ve belirli bir patterin yoluna girmesine izin vermeme ilkesine katılıyorum. AMA ECS bu önemsiz oyunu sapma olmadan halledemezse, büyük bir oyun için umut var. Ben de ECS'yi etkili bir şekilde kullanmayı öğrenmeye çalışıyorum, ancak ECS felsefesine mümkün olduğunca yakın kalmaya çalışıyorum, aksi takdirde, istisnalar ve özel durumlar yapmaya başladığımda, sürdürülemez bir karışıklıkla sonuçlanacağımı biliyorum.
Ken

-2

Bence *), Bileşenler ile ilgili en büyük sorun şudur: Bileşenler kimseye ne yapacağını söylemek için burada DEĞİLDİR . Bileşenler bir şeyler yapmak için burada. Sadece bir şeyin hafızasını tutacak bir bileşeniniz yok ve daha sonra bu konuda başka bileşenler çalışıyor. Sahip oldukları verilerle işleri yapan bileşenler istiyorsunuz.

Kendinizi diğer bileşenlerin varlığını test ederken görüyorsanız (ve daha sonra orada işlevleri çağırırsanız), bu açık bir işarettir, iki şeyden birinin doğru olduğunu gösterir:

  • Aslında bağımlılığı tersine çevirmek istiyorsunuz: Diğer bileşen, geçerli bileşeninize yanıt olarak mantıklarını yürütmek için olayları / mesajları / yayınları / kancaları / yine de dinlemelidir. Mevcut bileşenin bir "diğer" bileşen olduğunu bile bilmesine gerek yoktur. Mevcut yönteminize gerçekten bağlı olmayan işlevsellik ile farklı bileşenleri (başka / farklı bloklarda bile) çağırırken bulursanız, çoğu zaman bu durum söz konusudur. Tüm bunları Invalidate()veya SetDirty()diğer bileşenlere yapılan çağrıları düşünün .
  • Çok fazla bileşeniniz olabilir. İki bileşen birbiri olmadan yaşayamazsa ve sürekli olarak veri ve çağrı yöntemlerini birbirine alması gerekiyorsa, bunları birleştirin. Açıkçası, sağladıkları işlevsellik o kadar karışık ki, aslında tek bir şey.

Bu arada, bunlar yalnızca Varlık / Bileşen sistemleri için değil, aynı zamanda basit "GameObject" ler veya hatta kütüphane işlevlerine sahip klasik kalıtım için de geçerlidir.

*) Gerçekten sadece benim . Görüşler ağır yaklaşık değişir nedir Da Gerçek Bileşen Systemz (TM)

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.