RTS游戏单位结构


18

我想要一种方法来制作很多不同的单元,而不必多次编写诸如moveTo和Attack动作之类的东西

我的观察方式有两种。

  1. 具有标志的单个通用Unit类该类指定了它可以/不能执行的操作(然后在静态数组中创建实例,并在需要时获取它们)
  2. 对于具有特定于单元的操作(例如,Attack,Harvest,Patrol)具有抽象方法的抽象单元类,则所有这些都需要在子类中实现,即使该单元实际上无法收获任何东西。

第一种方法似乎最简单,但是我最终将为大多数单元使用大量代码。

第二种方法也可以。但是,如果我决定拥有两个可以收集资源的不同单元,那么我将在两个不同的类中拥有完全相同的代码,这似乎不是正确的方法。

这是解决这个问题的正确方法吗?
在像AoE这样的游戏中,我想每个单位都有某种动作/命令列表,我真的很想知道如何实现类似的目标,在这里我可以为每个动作/命令编写一次代码,并且然后将其提供给所有需要执行该操作的部门。

如果我不清楚(很有可能),或者您需要有关我到底在寻找什么的更多信息,请在评论中问我。

Answers:


25

一种常见的方法是采用基于组件的方法,其中基类“单元”仅实现所有单元共有的最基本方面,而每个单元则具有多个组件对象的列表,其中列出了其可以做什么以及它是如何做到的。

例如,罐可能具有分量MobileDestructibleAttacker,不移动只有炮塔DestructibleAttacker和收割机MobileDestructibleHarvester。然后,这些类将包括实现这些行为所需的所有代码。可以通过让组件检查另一个单元是否具有所需的组件,然后直接与该组件进行交互来实现组件之间的交互(Attacker只能损坏Destructible)。

与经典的类继承相比,优点是您可以轻松地组合能力。例如,当您想要一个也可以攻击,运输步兵和飞行的收割机时,您只需要添加必要的组件。您还可以轻松地以新组件的形式添加和删除新功能,而不必膨胀基本的Unit类。

Unity会在这种架构中为您提供支持,因为整个引擎已经基于组件。因此,可以将这些类似游戏逻辑的组件以脚本的形式添加。


因此,我会统一然后根据需要禁用和启用组件吗?
丹尼尔·霍尔斯特

@DanielHolst不,您将根据需要添加和删除它们。您可以在Unity编辑器中或通过使用gameObject.AddComponent和的脚本来实现gameObject.RemoveComponent
菲利普

好的,但是说一个“ moveTo”动作/命令。单位如何知道何时完成订单?我如何将订单排队?
丹尼尔·霍尔斯特

2
@DanielHolst我认为您误会了一些东西。该Moving组件表示“此单元通常可以移动”。不管设备是否在移动,组件都将永久连接到该组件。这并不意味着它现在正在移动。尽管您可以通过向MoveOrder组件添加组件,并在完成或取消订单后将该组件从设备中删除来做到这一点。
菲利普

1
@DanielHolst现在您正在转向AI单元,这是另一种蠕虫。一种可能的方法是拥有一个AIScript组件库,该库要么假定存在某些组件,要么根据单元具有的组件来更改其行为。但这确实是一个太复杂的话题,无法在评论中处理。
菲利普

4

许多游戏对实体使用基于组件的系统,在该系统中,可以将一系列行为和能力添加到更通用的单位类型中,而不是被编码为实体类(或等效类)的一部分。


这将很难实施吗?
Daniel Holst

这样的模式用于使整体实现更容易。如果您不能决定采用哪种方法,最好是尽可能简单地开始并随着更多功能的增长而选择。一旦对问题有了更多了解,就可以重构或重写为更适合您情况的方法。
罗斯泰勒-特纳

1
@DanielHolst我注意到您的问题有Unity国旗。Unity已经有一个内置的组件系统,并且强烈建议使用组合而不是继承。一种简单的方法是MonoBehaviour为每种操作类型创建一个,然后将其可以执行的操作附加到每个单元类型上(使用损坏类型和成本等每个类型的详细信息自定义操作实例)。这使您的单元创建保持数据驱动,因此您可以轻松地创建许多自定义单元类型。
DMGregory

@DanielHolst这取决于您对“极端困难”的定义。我的回答将详细介绍如何实现。
菲利普
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.