更好的课堂设计

时间:2017-10-13 14:01:33

标签: c++ oop inheritance unreal-engine4

我在虚幻引擎4中编写游戏。该引擎为您提供了几个类。在这个问题中,我将更多地关注类的连接而不是它们的目的。

引擎的类是这样的(" - >"与继承相关。例如A - > B表示A继承自B):
ACharacter - > APawn - > AActor - > ... - > UObject
" ..."只是无关紧要的课程 UObject类是引擎的主类,几乎引擎和游戏中的每个类最终都继承了UObject,另外它提供了我需要的许多功能。
继承是虚拟继承。这对未来很重要。我无法编辑任何引擎的类。

在我的游戏中有3个主要类: 建筑,生活和实体。
构建继承自 AActor和Entity
生活继承自两者 ACharacter和Entity

enter image description here

我创建了Entity类来关联建筑或生活而不重复我的代码。例如,Living类需要提供攻击另一个Living或Building的功能。所以我可以创建" AttackLiving"的2个功能。它有一个生活目标参数和一个功能" AttackBuilding"它具有Building目标参数,两个函数都具有完全相同的功能。相反,我创建了Entity类,所以我只有一个函数 - " AttackEntity"。当然这只是一个例子,我在整个代码中使用Entity类,所以我可以一次性引用Living和Building。

问题始于Entity类。一年前,当我实际创建它时,我犯了一个错误,我没有想到这一点。问题是Entity不从UObject继承。同样,UObject类是引擎的主类,它提供了我需要的许多功能。因为Entity不从UObject继承,所以我无法访问我需要的任何函数。

我不能让Entity从UObject或AActor继承,因为虚拟继承在这里不起作用。 (同样,引擎类继承不是虚拟继承)

我已经考虑过多种可能的解决方案。其中之一就是我可以随时将实体向下转换为构建或生活取决于实体的类型,而不是我可以使用UObject的功能。但这是一个非常难看的解决方案,它与实体的主体形成对比 - 与个人生活和建设无关。

此外,我已经考虑过在UObject类的实体中有一个指针,但是这是一个非常难看的解决方案,并没有解决所有问题。对于一个实例,Entity的另一个问题(它也不是从UObject继承):有一个名为" TWeakObjectPtr"的模板类。它在模板中获取一个类,为它创建一个指针并检查指针是否在引擎的任何其他位置都没有被释放。

TWeakObjectPtr<Entity> entityPointer;

问题是TWeakObjectPtr检查模板中给出的类是否继承自UObject,当然不是这样我不能使用TWeakObjectPtr。

总而言之,主要问题是Entity不是UObject的继承。但我确实需要它,所以我可以把生活和建筑联系在一起。

我很乐意,如果你可以提供一个保持实体的解决方案。提前谢谢!

1 个答案:

答案 0 :(得分:1)

我从未使用虚幻引擎,但希望下面的一些想法无论如何都会有用。

改善这种情况的一种方法是打破两个对象层次结构之间的继承链接 - 你的和引擎:

UOjbect <-- AActor <-- APawn <-- ACharacter
               |                    |
+------+       *                    |
|      |<-- Building                |
|Entity|                            *
|      |<------------------------ Living
+------+

其中*--表示聚合(或组合)。 您的类不继承引擎类,而是聚合适当的引擎对象。

Entity可以包含将返回getUnreal()的虚方法UObject,子类将返回AActorACharacter个对象 适当。 因此,只要您使用Entity,您就可以获得引擎对象,而不是直接获取引擎对象,而是通过entiry->getUnreal()调用。

反过来说,您可以从引擎类继承您的类,并使“实体”成为聚合行为而不是基类:

UOjbect <-- AActor <-- APawn <-- ACharacter
               ^                    ^
+------+       |                    |
|      |--* Building                |
|Entity|                            |
|      |------------------------* Living
+------+

在这里,您将使用需要引擎对象的Building / Living,但是当您想要引用自己的逻辑时,您将使用类似building->getEntity()的内容。 您可能有不同的Entity子类来实现BuildingLiving行为。

另外,我建议您查看Design Patterns: Elements of Reusable Object-Oriented Software本书,Structural Patterns章可能会帮助您找到更多想法。

相关问题