Dün, GDC Canada’dan Attribute / Behavior varlık sistemi hakkında bir sunum okudum ve bence oldukça güzel. Ancak, pratikte nasıl kullanılacağından emin değilim, sadece teoride değil. Her şeyden önce, bu sistemin nasıl çalıştığını hızlı bir şekilde açıklayacağım.
Her oyun varlığı (oyun nesnesi) niteliklerden (= davranışlarla erişilebilen veriler, aynı zamanda 'harici kod' ile de erişilebilir) ve davranışlardan (= OnUpdate()
ve içeren mantık OnMessage()
) oluşur. Bu nedenle, örneğin, bir koparma klon içinde, her tuğla meydana gelecek (örneğin!): PositionAttribute , ColorAttribute , HealthAttribute , RenderableBehaviour , HitBehaviour . Sonuncusu şuna benzeyebilir (sadece C # ile yazılmış çalışmayan bir örnek):
void OnMessage(Message m)
{
if (m is CollisionMessage) // CollisionMessage is inherited from Message
{
Entity otherEntity = m.CollidedWith; // Entity CollisionMessage.CollidedWith
if (otherEntity.Type = EntityType.Ball) // Collided with ball
{
int brickHealth = GetAttribute<int>(Attribute.Health); // owner's attribute
brickHealth -= otherEntity.GetAttribute<int>(Attribute.DamageImpact);
SetAttribute<int>(Attribute.Health, brickHealth); // owner's attribute
// If health is <= 0, "destroy" the brick
if (brickHealth <= 0)
SetAttribute<bool>(Attribute.Alive, false);
}
}
else if (m is AttributeChangedMessage) // Some attribute has been changed 'externally'
{
if (m.Attribute == Attribute.Health)
{
// If health is <= 0, "destroy" the brick
if (brickHealth <= 0)
SetAttribute<bool>(Attribute.Alive, false);
}
}
}
Bu sistemle ilgileniyorsanız, buradan daha fazla okuyabilirsiniz (.ppt).
Benim sorum bu sistemle ilgilidir, ancak genellikle her bileşen tabanlı varlık sistemi. Bunların hiçbirinin gerçek bilgisayar oyunlarında nasıl çalıştığını hiç görmedim, çünkü iyi örnekler bulamıyorum ve birini bulursam belgelenmemiş, yorum yok ve bu yüzden anlamıyorum.
Peki ne sormak istiyorum? Davranışlar nasıl tasarlanır (bileşenler). Burada, GameDev SE'de okudum, en yaygın hatanın birçok bileşen yapmak ve basitçe "her şeyi bir bileşen yapmak" olduğunu okudum. Bir bileşenin içinde görüntülemeyi yapmamanın önerildiğini okudum, ancak bunun dışında gerçekleştirin (yani RenderableBehaviour yerine, belki de RenderableAttribute olmalı ve eğer bir varlık RenderableAttribute true olarak ayarlanmışsa, o zaman Renderer
(sınıfla ilgili değil) bileşenleri, ancak motora kendisi) ekranda çekmek gerekir?).
Ancak, davranışlar / bileşenler ne durumda? Diyelim ki bir seviyem var ve seviyede bir Entity button
, Entity doors
ve var Entity player
. Oynatıcı düğmeyle çarpıştığında (bu baskıyla değiştirilen bir zemin düğmesidir), basılır. Düğmeye basıldığında, kapıları açar. Peki, şimdi nasıl yapılır?
Bunun gibi bir şeyle karşılaştım: oyuncunun birşeyle çarpışıp çarpışmadığını kontrol eden CollisionBehaviour var . Bir düğmeyle çarpışırsa CollisionMessage
, button
varlığa a gönderir . Mesaj gerekli tüm bilgileri içerecektir: düğme ile çarpışan. Düğme, alacak olan TogggeableBehaviour'a sahip CollisionMessage
. Kiminle çarpıştığını kontrol eder ve eğer varlığın ağırlığı düğmeyi değiştirecek kadar büyükse, düğme değiştirilir. Şimdi, düğmenin ToggledAttribute özelliğini true değerine ayarlar . Tamam, peki ya şimdi?
Düğme, değiştirildiklerini bildirmek için diğer tüm nesnelere başka bir mesaj göndermeli mi? Sanırım böyle bir şey yaparsam binlerce mesajım olur ve oldukça karışık olur. Bu yüzden belki bu daha iyidir: kapılar, bunlara bağlı olan düğmeye basılıp basılmadığını kontrol eder ve OpenedAttribute özelliğini buna göre değiştirir. Fakat o zaman kapıların OnUpdate()
yönteminin sürekli bir şeyler yapacağı anlamına gelir (bu gerçekten bir sorun mu?).
Ve ikinci problem: daha fazla çeşit butonum varsa. Biri baskıyla bastırılır, ikincisi şutla vurulur, üçüncüsü üzerine su dökülürse değiştirilir, bu da bunun gibi farklı davranışlara sahip olmak zorunda kalacağım anlamına gelir:
Behaviour -> ToggleableBehaviour -> ToggleOnPressureBehaviour
-> ToggleOnShotBehaviour
-> ToggleOnWaterBehaviour
Gerçek oyunlar böyle mi çalışıyor, yoksa ben sadece aptal mıyım? Belki sadece bir olabilir ToggleableBehaviour ve uygun davranması gerekir ButtonTypeAttribute . Yani eğer öyleyse ButtonType.Pressure
, bunu yapar, eğer öyleyse ButtonType.Shot
, başka bir şey yapar ...
Peki ben ne istiyorum? Doğru mu yapıyorum yoksa sormak isterim, yoksa sadece aptalım ve bileşenlerin amacını anlamadım. Bileşenlerin oyunlarda gerçekte nasıl çalıştığına dair iyi bir örnek bulamadım, bileşen sisteminin nasıl yapılacağını açıklayan bazı dersler buldum, ancak nasıl kullanılacağını öğretmedim.