2012-09-11 41 views
6

Kodumdaki bir şeyin örnek olayını, ne demek istediğimin bir örneği olarak kullanacağımı düşünüyorum.Arabirimde kalıtım/hiyerarşiler. Net - daha iyi bir yolu var mı?

Şu anda bileşen tabanlı oyun sistemim için bir davranış/eylem sistemi üzerinde çalışıyorum. GameObjects sadece ilgili ayrıntıları gösteren bir IBehaviorComponent ve bunlara bağlı bir IActionComponent sahip olabilir, aşağıdaki maruz:

public interface IBehaviorComponent : IBaseComponent 
{ 
    IBehavior Behavior { get; } 
} 

public interface IActionComponent : IBaseComponent 
{ 
    IAction Action { get; } 
    void ExecuteAction(IGameObject target = null); 
} 

Şimdi, bu şimdiye kadar bütün ince (en azından bana!). Ancak, IActionComponent uygulamalarına baktığımda sorun demlemeye başlıyor. Örneğin

, basit IActionComponent uygulaması:

public class SimpleActionComponent : IActionComponent 
{ 
    public IAction Action { get; protected set; } 

    public void ExecuteAction(IGameObject target = null) 
    { 
     Action.Execute(target); 
    } 

    public void Update(float deltaTime) { } //from IBaseComponent 
} 

Fakat, bu reklam eylemleri zamanlanmış bir program üzerinde yürütülecek için izin veren daha karmaşık IActionComponent uygulanmasını tanıtmak istiyorum diyelim:

public class TimedActionComponent : IActionComponent 
{ 
    public IAction Action { get; protected set; } 

    public float IdleTime { get; set; } 

    public float IdleTimeRemaining { get; protected set; } 

    public void ExecuteAction(IGameObject target = null) 
    { 
     IdleTimeRemaining = IdleTime; 
    } 

    public void Update(float deltaTime) 
    { 
     if (IdleTimeRemaining > 0f) 
     { 
     IdleTimeRemaining -= deltaTime; 
     } 
     else 
     { 
     Action.Execute(target); 
     } 
    } 
} 

Ve şimdi, IdleTime'ı dışarıdan etkilerle değiştirilebilecek şekilde göstermek istiyorum.

public interface ITimedActionComponent : IActionComponent 
{ 
    float IdleTime { get; set; } 

    float IdleTimeRemaining { get; set; } 
} 

Ancak burada mesele benim bileşen sistem IBaseComponent itibaren bir düzey yukarı her şeyi saklar olmasıdır: ilk başta Düşüncelerim yeni bir arayüz oluşturmak için idi. Yani, bir GameObject için eylem bileşeni, bir IAimedActionComponent veya bir IRandomizedActionComponent veya bir ICrashTheProgramActionComponent gibi bir IActionComponent olarak alınır. Umarım bunun nedenleri açıktır, çünkü GameObject'i bileşenlerden biri için temel bileşen türünün (IActionComponent, IRenderableComponent, IPhysicsComponent, vb.) Ötesinde ne istediğini tam olarak bilmek zorunda kalmadan sorgulayabileceğimiz bir şey istiyorum.

Bunu temizlemenin daha iyi bir yolu var mı, bu özellik, alınan IActionComponent öğesinin ilgisini çeken türe dönüştürmek zorunda kalmadan, alt sınıflarda tanımlanan bu özellikleri göstermeme izin verecek mi? Ya da bunu gerçekleştirmenin tek/en iyi yolu budur. Bir şey gibi: Şu anda

public void IWantYouToAttackSuperSlow(IGameObject target) 
{ 
    //Let's get the action component for the gameobject and test if it's an ITimedActionComponent... 
    ITimedActionComponent actionComponent = target.GetComponent<IActionComponent>() as ITimedActionComponent; 

    if (actionComponent != null) //We're okay! 
    { 
     actionComponent.IdleTime = int.MaxValue; //Mwhaha 
    } 
} 

O Only Wayvar düşünüyorum, ama ben cahil değilim, ya da ahşap saklandığı bir model var mı, olacak göreyim herkes bir önerebilir Bunu başarabilmek için daha iyi bir yol.

Teşekkürler!

+0

Benim diğer düşünce böyle yönelecek IActionComponentExecutor olarak, içinde başka bir nesne kullanmaktı oh ~ biz kurumsal y şimdi oluyoruz (harici nesneler daha sonra IActionComponentTimedExecutor izini olacak - Action.Execute() çağırmasını karar, ama bu yuvarlak-a-butik moda silbaştan getiriyor düşünüyorum !) IdleTime'ı değiştirmek için. – Terminal8

+0

İlgilenmiyorum - actionComponent.IdleTime durumu bir tür genel çantada saklanır mı? Eğer öyleyse, temel arayüzünüzde 'Uygula (BagData bag)' ve 'Store (BagData bag) 'yöntemlerini kullanabilirsiniz. Bununla birlikte, türetilmiş türleri bilmeye ihtiyaç duyan özellikleri sorgulamak için kullanabileceğiniz bazı meta veri türlerini de göz önünde bulundurmanız gerekebilir. 'TypeDescriptor' özellik ızgaraları vb gibi şeyler tarafından kullanılan hazır bir başlangıç ​​noktasıdır. –

+0

Hayır, şu anda değil. Ben de bu konseptle aşina değilim - belki de sağlayabileceğiniz bir referans var mı? – Terminal8

cevap

0

Haklısınız, belirli bir uygulama için alt türlere dökerek sınamak iyi bir fikir değil. Sağladığınız örneklerden, üzerinde işlem yapmak istediğiniz bir IGameObject var gibi görünüyor. Senin IActionComponent yerine IGameObject bir argüman olarak bir yöntem ortaya çıkarmak yerine, başka bir şekilde bunu yapabilirsiniz, yani, IGameObject, bir ya da çok isterseniz, yürütmek yapabileceğiniz eylemleri bir olsun. yürütme yönteminde sonra

interface IActionComponent 
{ 
    ExecuteAction(); 
} 

interface IGameObject 
{ 
    IActionComponent ActionComponent { get; } 
} 

Eğer IActionComponent nasıl uyguladıklarını bağlı
public void IWantYouToAttackSuperSlow(IGameObject target) 
{ 
    target.ActionComponent.ExecuteAction(); 
} 

yapın polimorfizmi doğru kod çalıştırıldığında sağlayacağız.

ihtiyacını uygun görünüyor Command Pattern denilen bir model vardır.

+0

Ah, burada sağladığım örnek olay çalışması, içinde çalıştığım bu arabirim mirasının yalnızca bir örneğiydi. Bileşen tabanlı bir sistem geliştirdiğim için, IGameObject * sadece * herhangi bir "gerçek" bileşen hakkında kesinlikle hiçbir mantık veya bilgi olmadan, bileşenler için son derece basit bir kaptır. Özünde, belirli bir “varlık” ı kaplayan bileşenlerin bu “varlığa” bağlı olmasına izin veren bir GUID'dir (ancak bu kavramın bir arabirim/sınıfta kolay bileşen geri kazanımı sağlamak için kapsandım). – Terminal8

+0

@Icelight: Mimarinizi tam olarak anlayama iddiasında bulunamıyorum. Ancak, cümleniniz * "IGameObject, bileşenler için son derece basit bir kaptır, kesinlikle mantıksızdır." * * Bana garip geliyor. Ne zaman bir “mantığa gerek duymadan, sadece bir çanta torbası olmalı” diye bir ders duyduğumda, nesne yönelimli programlama hakkında öğrendiğim ilk şeyi hatırlatıyorum: ** veriler **. Yani, bence, mantıksız sınıflar biraz kod kokusu. –

+0

@sJhonny: Ne yaptığınızı anlıyorum. Ancak, bu durumda, ihtiyaç olmaktan ziyade benim için kolaylık sağlamak amacıyla bir GameObject kuruldu. "Gerçek" bileşen tabanlı bir oyun sisteminde, bileşenlerin tümü, büyük bir bileşen bulutunda (veya daha büyük olasılıkla, bileşen türlerine adanmış yöneticilerin içinde otururken), yalnızca bir GUID bağlayanlar gibi Aynı varlık için birlikte. Bu yaklaşımı almaktan ziyade, aynı varlığın tüm bileşenlerini tutan bir GameObject kullanıyorum - kolaylık, çünkü bu yaklaşım benim için görselleştirmekten daha kolaydır. – Terminal8

1

kod bunu atmalarını aşağı bir IActionComponent bir ITimedActionComponent olduğu için (bildiğim kadarıyla gördüğünüz gibi) bunları kullanmak için IdleTime özelliklerinin farkında olmak zorunda unavoidable-, sağ gösterdi?

Buradaki hilenin, IActionComponent numaranızı kullanan sınıfların onunla uğraşmak zorunda kalmayacak kadar hoş olmayan bir kodu gizlemek olduğunu düşünüyorum. Bu nasıl yapılacağına ilişkin
ilk düşüncem kullanmaktır bir Factory:

public void IWantYouToAttackSuperSlow(IGameObject target) 
{ 
    //Let's get the action component for the gameobject 
    IActionComponent actionComponent = ActionComponentsFactory.GetTimedActionComponentIfAvailable(int.MaxValue); 
} 

ve fabrikanın yöntemi:

public IActionComponent GetTimedActionComponentIfAvailable(IGameObject target, int idleTime) 
{ 
var actionComponent = target.GetComponent<IActionComponent>() as ITimedActionComponent; 

    if (actionComponent != null) //We're okay! 
    { 
     actionComponent.IdleTime = int.MaxValue; //Mwhaha 
    } 
return (actionComponent != null)? actionComponent : target.GetComponent<IActionComponent>(); 
} 
+0

İlk cümleninizle ilgili olarak - hemfikirim ve bunun etrafında gerçek bir yol göremiyorum. Sanırım her şeyi tamir edebilecek bir mucize mimarisi için balıkçılık/dua ediyordum. Ama sanırım henüz tam orada değiliz;) Fabrika yöntemine gelince, bunu çok beğendim ve en azından bazı şeyleri temizlemeye yardımcı olacak. Bunun şu an sahip olduğum şeyle ne kadar iyi çalışacağına bakacağım. – Terminal8

İlgili konular