处理对象之间的交互

时间:2012-07-04 06:18:40

标签: c# object unity3d interaction

我目前正在团结一致做几场比赛。我正在使用C#。我通常对游戏中的代码感到满意,我知道如何使它“优雅”,可以这么说。我非常善于编写单个元素(Say,Asteroids中的宇宙飞船)。但我对代码感到满意,直到我到达一个对象需要与另一个对象交互的程度。在那之后它变成了代码意大利面,我总是放弃这个项目。我还没有找到一种处理事物的优雅方式。我相信我已经在互联网的各个地方提出过要求,但我似乎不断回到这一点。

是否有任何处理对象之间交互的常用方法?什么都不觉得hacky?我的最新项目再次出现了这个问题。这是一个Unity项目,一个2d sidescroller。检测我是否用我的角色命中“尖峰”包括检查碰撞对象标签并查看它是否是“尖峰”。但是我的所有“死亡”代码都包含在播放器中,而不是尖峰。除了带有标签的网格对撞机之外,尖峰不是其他任何东西。这感觉不对。

所以stackoverflow,你们怎么处理这个?

3 个答案:

答案 0 :(得分:3)

这通常是大项目发生的事情,他们开始非常好,最终成为大怪物。在编写面向对象的应用程序时,我发现了一些有用的原则:

  1. 以自上而下的方式进行OOAD分析,从您的域名问题开始深入到类图
  2. 始终将您的应用程序分成多个层(实用程序,数据访问,业务对象,UI ...)
  3. 最重要的是,实施GRASP patterns以确保您的对象具有正确的职责,以自然的方式进行交互,而不是高度耦合。

答案 1 :(得分: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);
    }
}

答案 2 :(得分:2)

正如Johnn Blade在评论中留下的那样,使用Observer Pattern可能是在应用程序的不同部分之间传递状态更改的好方法。

作为一个具体的例子,您可以将玩家移动分解为应用程序的其他部分可以观察到的几个不连续的步骤(或事件)。

例如,如果您将以下事件添加到播放器:

  • BeforeMove(Coordinate oldCoordinate,Coordinate newCoordinate,out bool canMove)
  • 已移动(Coordinate oldCoordinate,Coordinate newCoordinate)
  • HealthChanged(int newHealth)

场景中的其他对象可能包含以下事件:

  • DamagePlayer(int damage)
  • HealPlayer(int heal)

当您要移动玩家时,您将触发BeforeMoved事件 - 如果没有任何响应canMove = false(例如锁定的门),则允许移动。然后你更新玩家的位置,并调用Moved。

所以,你的Spike可以监听玩家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事件,当它达到零或更低时,会杀死玩家。

使用此模式,添加检测下降等新功能相对简单。只需创建Moved事件的新观察者:

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)); 
  }
}