【问题标题】:Handling interaction between objects处理对象之间的交互
【发布时间】:2012-07-04 06:18:39
【问题描述】:

我目前正在团结一致地制作一些游戏。我正在使用 C#。我通常对我的游戏中的代码很满意,我知道如何让它“优雅”,可以这么说。我非常擅长对单个元素进行编码(例如,小行星中的宇宙飞船)。但我只对我的代码感到满意,直到我达到一个对象需要与另一个对象交互的地步。在那之后它变成了代码的意大利面条,我总是放弃这个项目。我还没有找到一种优雅的方式来处理事情。我相信我在互联网上的各个地方都问过,但我似乎一直在问这个问题。

是否有任何处理对象之间交互的通用方法?任何不让人觉得hacky的东西?这个问题在我最近的项目中再次出现。这是一个 Unity 项目,一个 2d 横向卷轴。检测我是否用我的角色击中“尖峰”涉及检查碰撞对象标签并查看它是否是“尖峰”。但是我所有的“死亡”代码都包含在播放器中,而不是尖峰。尖峰实际上只是带有标签的网格对撞机。这感觉不对。

那么stackoverflow,你们都是怎么处理的呢?

【问题讨论】:

标签: c# object unity3d interaction


【解决方案1】:

这通常发生在大型项目中,它们开始时非常顺利,最终变成了巨大的怪物。以下是我在编写面向对象应用程序时发现的一些有趣的有用原则:

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

【讨论】:

    【解决方案2】:

    除了设计模式之外,这些设计模式总是值得考虑的:
    我建议不要使用标签,而是为类似的东西创建组件。它们是 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);
        }
    }
    

    【讨论】:

      【解决方案3】:

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

      作为一个具体的例子,您可以将玩家的运动分解为几个离散的步骤(或事件),这些步骤(或事件)可以被应用程序的其他部分观察到。

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

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

      而场景中的其他物体可能有事件如:

      • DamagePlayer(int 伤害)
      • HealPlayer(int 治愈)

      当你要移动一个玩家时,你会触发 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)); 
        }
      } 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-21
        • 2016-01-15
        • 2019-01-12
        相关资源
        最近更新 更多