Fizik veya grafik bileşenleri tipik olarak bileşen odaklı bir sistemde nasıl oluşturulur?


19

Son 48 saati Nesne Bileşeni sistemlerini okumak için harcadım ve uygulamaya başlamak için yeterince hazır olduğumu hissediyorum. Oluşturulan temel Nesne ve Bileşen sınıfları var, ama şimdi ben gerçek bileşenleri oluşturmaya başlamak gerekir biraz kafam karıştı. Bunları HealthComponent veya temelde sadece bir mülk olabilecek bir şey olarak düşündüğümde, bu mükemmel bir mantıklı. Bir Fizik / Grafik bileşeni olarak daha genel bir şey olduğunda, biraz kafam karışır.

Object sınıfım şu ana kadar benziyor (Yapmam gereken herhangi bir değişiklik fark ederseniz lütfen bana bildirin, hala yeni) ...

typedef unsigned int ID;

class GameObject
{
public:

    GameObject(ID id, Ogre::String name = "");
    ~GameObject();

    ID &getID();
    Ogre::String &getName();

    virtual void update() = 0;

    // Component Functions
    void addComponent(Component *component);
    void removeComponent(Ogre::String familyName);

    template<typename T>
    T* getComponent(Ogre::String familyName)
    {
        return dynamic_cast<T*>(m_components[familyName]);
    }

protected:

    // Properties
    ID m_ID;
    Ogre::String m_Name;
    float m_flVelocity;
    Ogre::Vector3 m_vecPosition;

    // Components
    std::map<std::string,Component*> m_components;
    std::map<std::string,Component*>::iterator m_componentItr;
};

Şimdi karşılaştığım sorun, genel nüfusun Fizik / Grafik gibi Bileşenlere ne koyacağıdır? Ogre (oluşturma motorum) için görünür Nesneler, sahneye eklemek için birden fazla Ogre :: SceneNode (muhtemelen çoklu), görünür kafesleri göstermek için Ogre :: Entity (muhtemelen çoklu) ve benzerlerinden oluşur. Nesneye yalnızca birden fazla GraphicComponent eklemek ve her GraphicComponent'in bir SceneNode / Entity işlemesine izin vermek en iyisi midir, yoksa her bir Bileşenden birine sahip olma fikri gerekli midir?

Fizik için daha da kafam karıştı. Sanırım belki bir RigidBody yaratıyor ve kütle / interiyumu / vb. mantıklı olurdu. Ama detayları bir Bileşene nasıl koyacağımı düşünmekte güçlük çekiyorum.

Bu "Gerekli" bileşenlerden birkaçını tamamladıktan sonra, çok daha mantıklı olacağını düşünüyorum. Şu an itibariyle hala biraz gerginim.

Yanıtlar:


32

Her şeyden önce, sen inşa bileşen tabanlı sistemler, sen yokken var dönüm yaklaşım benimsemeye her şeyi bir bileşeni haline. Aslında, genellikle yapmamalısınız - bu bir neofit hatasıdır. Deneyimlerime göre, bileşen tabanlı bir mimaride render ve fizik sistemlerini birleştirmenin en iyi yolu, bu bileşenleri gerçek renderleme veya fizik ilkel nesnesi için aptal kaplardan biraz daha fazla yapmaktır.

Bu, oluşturma ve fizik sistemlerinin bileşen sisteminden ayrılmasını sağlama avantajına sahiptir.

Fizik sistemleri için, örneğin, fizik simülatörü genellikle her tıkladığında manipüle ettiği sert vücut nesnelerinin büyük bir listesini tutar. Bileşen sisteminiz bununla uğraşmaz - fizik bileşeniniz, bileşenin ait olduğu nesnenin fiziksel yönlerini temsil eden katı gövdeye bir referans depolar ve bileşen sisteminden gelen mesajları katı gövdenin uygun manipülasyonlarına dönüştürür.

Oluşturma işleminde olduğu gibi, oluşturucunuzda oluşturulacak örnek verilerini temsil eden bir şey olur ve görsel bileşeniniz buna bir referans tutar.

Bu nispeten basit - nedense insanları karıştırıyor gibi görünüyor, ama bunun nedeni genellikle çok fazla düşünüyorlar. Orada çok fazla sihir yok. Ve mükemmel tasarım üzerinde agonize olmaktan ziyade işlerin yapılması en önemli şey olduğu için, en azından bazı bileşenlerin arayüzleri tanımladığı ve momboco'nun önerdiği gibi oyun nesnesinin doğrudan üyeleri olduğu bir yaklaşımı güçlü bir şekilde düşünmelisiniz. Bu aynı derecede geçerli bir yaklaşım ve daha kolay anlaşılır.

Diğer yorumlar

Bu doğrudan sorularınızla ilgisizdir, ancak bunlar kodunuza bakarken fark ettiğim şeyler:

Görünüşte grafik olmayan bir nesne olan ve dolayısıyla Ogre'ye bağımlı olmaması gereken oyun nesnenizde neden Ogre :: String ve std :: string'i karıştırıyorsunuz? Dönüşüm gerçekleştirmeniz gereken oluşturma bileşeninin kendisi dışında Ogre'ye yapılan tüm doğrudan başvuruları kaldırmanızı öneririm.

update (), bir bileşen mimarisiyle gitmek istediğiniz yönün tam tersi olan GameObject öğesinin alt sınıfının olması gerektiğini ima eden saf bir sanaldır. Bileşenleri kullanmanın ana noktası, kalıtımdan ziyade işlevsellik toplamasını tercih etmektir.

Bazı kullanımlarından faydalanabilirsiniz const(özellikle referans olarak geri döndüğünüz yer). Ayrıca, hızın gerçekten bir skaler olmasını istediğinizden emin değilim (veya oyun nesnesinde, gittiğiniz gibi aşırı jenerik bileşen metodolojisi türünde olması gerekiyorsa).

Büyük bir bileşen haritası ve update()oyun nesnesindeki bir çağrı kullanma yaklaşımınız oldukça düşük optimaldir (ve bu tür sistemleri ilk inşa edenler için ortak bir tuzaktır). Güncelleme sırasında çok zayıf bir önbellek tutarlılığı sağlar ve eşzamanlılıktan ve aynı anda büyük veri veya davranış yığınlarının SIMD stili işlemine yönelik eğilimden yararlanmanıza izin vermez. Oyun nesnesinin bileşenlerini güncellemediği bir tasarım kullanmak genellikle daha iyidir, aksine bileşenin kendisinden sorumlu alt sistem hepsini bir kerede günceller. Bu okumaya değer olabilir.


Bu cevap mükemmeldi. Hala yorumlarda paragrafları boşluk bırakmanın bir yolunu bulamadım (enter tuşuna sadece gönderir) ama bu yanıtları ele alacağım. Object / Component sistemi tanımınız çok anlamlı. Bu nedenle, bir PhysicsComponent durumunda, bileşenin yapıcısında, sadece PhysicsManager'ım CreateRigidBody () işlevini çağırabilir ve bileşene bir başvuru depolayabilir miyim?
Aidan Knight

"Diğer Yorumlar" kısmına gelince, bunun için teşekkürler. Dizeleri karıştırdım çünkü genellikle tüm Ogre işlevlerini Ogre kullanan projem için bir temel olarak kullanmayı tercih ediyorum, ancak map / pair / etc'den yoksun olduğundan Nesne / Bileşen sisteminde değiştirmeye başladım. Gerçi haklısın ve onları Ogre'den ayırmak için std üyelerine dönüştürdüm.
Aidan Knight

1
+1 Bu, bir süredir burada okuduğum bileşen tabanlı bir modelle ilgili ilk aklı başında cevap, aşırı genellemeye karşı güzel bir kontrast
Maik Semder

5
Daha iyi tutarlılık sağlar (hem verilerde hem de talimat önbelleğinde) ve güncellemeleri neredeyse ayrı bir iş parçacığına veya çalışan işlemciye (örneğin SPU'lar) neredeyse önemsiz bir şekilde yükleme olasılığını sunar. Bazı durumlarda, bileşenlerin herhangi bir şekilde güncellenmesi bile gerekmez, bu da bir update () yöntemine op-free çağrısının yüklenmesini önleyebilirsiniz. Ayrıca veri odaklı sistemler oluşturmanıza yardımcı olur - tamamen CPU mimarisindeki modern trendlerden yararlanan toplu işleme ile ilgilidir.

2
+1 "oldukça mükemmel tasarımı üzerinde agonize daha halletmek için en önemli"
Trasplazio Garzuglio

5

Bileşen mimarisi, aynı düğümden tüm öğeleri miras alan büyük hiyerarşilerden ve yol açan bağlantı sorunlarından kaçınmak için bir alternatiftir.

"Genel" bileşenler içeren bir bileşen mimarisi gösteriyorsunuz. "Genel" bileşenler eklemek ve ayırmak için temel mantığınız vardır. Jenerik bileşenlere sahip bir mimariye ulaşmak daha zordur, çünkü hangi bileşenin olduğunu bilmiyorsunuz. Faydaları, bu yaklaşımın genişletilebilir olmasıdır.

Tanımlanmış bileşenlerle geçerli bir bileşen mimarisi elde edilir. Tanımlanmış ile demek istediğim, arayüz değil uygulama tanımlanır. Örneğin, GameObject bir IPhysicInstance, Transformation, IMesh, IAnimationController öğesine sahip olabilir. Bu, arabirimi ve GameObject'in her bileşenle nasıl başa çıkacağını bilmesi avantajına sahiptir.

Aşırı genelleme terimine yanıt verme

Bence kavramlar net değil. Bileşen dediğimde, bir oyun nesnesinin tüm bileşenlerinin bir bileşen arabiriminden veya benzer bir şeyden miras alması gerektiği anlamına gelmez. Ancak bu Genel Bileşenler için yaklaşımdır, bence bileşen olarak adlandırdığınız kavram budur.

Bileşen mimarisi, çalışma zamanı nesne modeli için var olan mimarilerden biridir. Tüm durumlar için tek ve en iyisi değil, ancak deneyim, düşük kuplaj gibi birçok faydası olduğunu gösterdi.

Bileşen mimarisini ayırt eden ana özellik, ilişkinin-a'yı has-a'ya dönüştürmesidir. Örneğin bir nesne mimarisi-a:

bir mimari

Bir nesne mimarisi yerine has-a (bileşenler):

has-a mimarisi

Ayrıca mülk merkezli mimariler de vardır:

Örneğin, normal bir nesne mimarisi şöyledir:

  • Object1

    • Pozisyon = (0, 0, 0)
    • Yön = (0, 43, 0)
  • Object2

    • Pozisyon = (10, 0, 0)
    • Yön = (0, 0, 30)

Mülk merkezli bir mimari:

  • Durum

    • Object1 = (0, 0, 0)
    • Object2 = (10, 0, 0)
  • Oryantasyon

    • Nesne1 = (0, 43, 0)
    • Object2 = (0, 0, 30)

Nesne modeli mimarisi daha iyi mi? Performans açısından, daha önbellek dostu olduğu için mülk merkezli daha iyidir.

Bileşen has-a yerine--ilişkisine atıfta bulunur. Bir bileşen bir Dönüşüm matrisi, bir kuaterniyon, vb. Olabilir. Ancak, oyun nesnesiyle olan ilişki bir ilişkidir, oyun nesnesinin dönüşümü yoktur, çünkü devralınmıştır. Oyun nesnesi dönüşüme sahiptir (ilişki vardır-a). Dönüşüm o zaman bir bileşendir.

Oyun nesnesi bir hub gibidir. her zaman orada olan bir bileşen istiyorsanız, belki de bileşen (matris gibi) bir işaretçinin değil nesnenin içinde olmalıdır.

Tüm durumlar için mükemmel bir oyun nesnesi yoktur, motora, motorun kullandığı kütüphanelere bağlıdır. Belki kafesi olmayan bir kamera istiyorum. Sorun, bir mimarinin sorunudur, eğer oyun-nesnesi bir ağa sahipse, o zaman oyun-nesnesinden miras alan kameranın bir ağa sahip olması gerektiğidir. Bileşenlerle, kamerada bir dönüşüm, hareket için bir denetleyici ve ihtiyacınız olan her şey bulunur.

Daha fazla bilgi için, "Jason Gregory" nin "Oyun Motoru Mimarisi" kitabındaki "14.2. Çalışma Zamanı Nesne Modeli Mimarisi" bölümü özellikle bu konuyu ele almaktadır.

UML diyagramları oradan çıkarılır


Son paragrafa katılmıyorum, aşırı genelleme eğilimi var. Bileşen tabanlı model, her işlevin bir bileşen olması gerektiği anlamına gelmez, yine de işlevsellik ve veri ilişkilerini dikkate almak gerekir. Mesh olmayan bir AnimationController işe yaramaz, bu yüzden ait olduğu yere mesh içine koyun. Dönüşümü olmayan bir Oyun Nesnesi bir Oyun Nesnesi değildir, tanım gereği 3D dünyasına aittir, bu yüzden onu Oyun Nesnesine normal bir üye olarak koyun. Kapsülleme işlevselliği ve verilerin normal kuralları hala geçerlidir.
Maik Semder

@Maik Semder: Genel anlamda aşırı genelleme konusunda size katılıyorum, ancak bileşen teriminin açık olmadığını düşünüyorum. Cevabımı düzenledim. Okuyun ve bana izlenimlerinizi verin.
momboco

momboco iyi, aynı noktaları daha az tekrarladınız;) Transform ve AnimationController hala benim görüşüme göre bileşen modelinin aşırı kullanımı olan bileşenler olarak tanımlanıyor. Anahtar ne bir bileşeni haline konulmalıdır ve ne tanımlamak değildir:
Maik Semder

Game-Object'in (GO) ilk etapta çalışması için bir şey gerekiyorsa, başka bir deyişle isteğe bağlı değil, zorunlu ise, o zaman bir bileşen değildir. Bileşenlerin isteğe bağlı olması gerekir. Dönüşüm iyi bir örnektir, bir GO için isteğe bağlı değildir, Transform'suz bir GO mantıklı değildir. Öte yandan, her GO'nun fiziğe ihtiyacı yoktur, bu yüzden bir bileşen olabilir.
Maik Semder

AnimationController (AC) ve Mesh arasında olduğu gibi 2 işlev arasında güçlü bir ilişki varsa, AC'yi bir bileşene basarak bu ilişkiyi koparmayın, aksine Mesh mükemmel bir bileşendir, ancak AC Mesh içine.
Maik Semder
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.