2012-07-04 47 views
1

我目前正在團結工作,做幾個遊戲。我正在使用C#。我通常對遊戲中的代碼感到滿意,我知道如何使它「優雅」,可以這麼說。我非常善於編碼單個元素(比如說,在小行星中的飛船)。但我只對我的代碼感到滿意,直到一個對象需要與另一個對象交互爲止。它成爲代碼意大利麪之後,我總是放棄項目..我還沒有找到一個處理事情的優雅方式。我相信我已經在互聯網上的各個地方問過,但我似乎一直在回來。處理對象之間的互動

是否有任何處理對象間交互的常用方法?任何不覺得哈克?這個問題在我的最新項目中再次出現。這是一個Unity項目,一個2d sidescroller。檢測我是否與我的角色碰撞'尖峯'涉及檢查碰撞對象標籤並查看它是否是'尖峯'。但是,我所有的「死亡」代碼都包含在玩家中,而不是高峯期。除了具有標籤的網格對撞機之外,尖峯實際上並不是什麼。這感覺不對。

所以,stackoverflow,你們如何處理這個?

+0

看看中保設計模式 – Mithir

+1

還是看看觀察者模式http://www.dofactory.com/Patterns/PatternObserver.aspx – JohnnBlade

+0

我認爲OP的問題是針對GRASP這樣的高層次模式 – GETah

回答

2

正如Johnn Blade在對該問題的評論中留下的,使用Observer Pattern可能是在應用程序的不同部分之間溝通狀態更改的好方法。作爲一個具體的例子,你可能會把玩家的移動分解成幾個可以被應用程序的其他部分觀察到的離散步驟(或事件)。

例如,如果您添加以下事件給玩家:

  • BeforeMove(座標oldCoordinate,座標newCoordinate,OUT BOOL canMove)
  • 移動(座標oldCoordinate,座標newCoordinate)
  • HealthChanged (INT newHealth)

和場景中的其他對象可以具有事件,例如:

  • DamagePlayer(INT損壞)
  • HealPlayer(INT癒合)

當你欲動的球員,你會觸發BeforeMoved事件 - 如果沒有與canMove = false響應(如鎖上大門) ,那麼這個舉動是被允許的。然後你更新玩家的位置,並調用Moved。

所以,你可以秒殺監聽玩家感動的事件:

void Moved(Coordinate oldCoordinate, Coordinate newCoordinate) 
{ 
    if (newCoordinate.Intersects(this.Location)) 
    { 
    DamagePlayer(50); 
    } 
} 

相應播放器將監聽DamagePlayer事件。

void DamagePlayer(int damage) 
{ 
    this.Health -= damage; 
    HealthChanged(this.Health); 
} 

東西(可能在玩家本身)會聽取HealthChanged事件,當它達到零或更少時,殺死玩家。

使用此模式,添加檢測下降等新功能相對簡單。只要創建的感動事件的新的觀察員:

void Moved(Coordinate oldCoordinate, Coordinate newCoordinate) 
{ 
    decimal deltaY = oldCoordinate.Y - newCoordinate.Y; 
    if (deltaY < -100) // If fell 100 units or more, take 10 damage per unit. 
    { 
    DamagePlayer(10 * Math.Abs(deltaY)); 
    } 
} 
3

這通常是發生在大型項目上的事情,它們開始非常好,最終成爲大怪物。這裏有幾個有用的原則,我發現有趣書寫時面向對象的應用程序:

  1. 做開始與您的域名問題,探究問題的類圖
  2. 在使用應用程序分離成一個自上而下的方式您的OOAD分析層(實用程序,數據訪問,業務對象,用戶界面...)
  3. 而最重要的是,實施GRASP patterns以確保您的對象有正確的責任,以自然的方式進行交互,而不是高度耦合。
3

此外,對於設計模式,這是一件好事,考慮:
而不是使用標籤的,我會建議創建這樣的事情組件。它們是Unity3d的核心概念之一,並且更具可重用性。

例如,您可以創建一個類型爲DamageVolume或類似的新組件。這會使它更通用,你可以重用它來損害你的播放器。你也可以用InstantKillDamageType(這將允許玩家決定他如何死亡或玩什麼效果)或DamageAmount等屬性進行配置。在您的播放器的碰撞事件,你可以做這樣的事情,那麼:

var damager = collision.gameobject.GetComponent<DamageVolume>(); 
if (damager != null) { 
    if (damager.InstantKill) { 
     this.Kill(damager.DamageType); 
    } 
    else { 
     this.Damage(damager.DamageAmount, damager.DamageType); 
    } 
}