UE4 | 多人游戏#2的库存| 将蓝图连接到C ++




游戏模式上一篇文章中,我讨论了如何创建DataAsset ,以及为什么它是如此方便和美观。 在这里,我们将研究如何从BlueprintC ++访问DataAsset ,更准确地说是分配给它的数据。


在此过程中,我们将回答从C ++访问任何蓝图的问题。




通过Blueprints交互,一切都变得非常透明。
由于我们已经关闭对数据库的直接访问,因此我们不能仅从Blueprint访问它。 注意保护:在下面的代码中。


protected: /* This is the main Database for all Items. It contains constant common variables */ UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "ItemsDatabase") TMap<FGameplayTag, FItemsDatabase> ItemsDataBase; 

即 我们的存储库仅在继承的类中可见,这很好,因为我们已经编写了用于安全调用数据的函数。


 /* Used in the widget */ UFUNCTION(BlueprintCallable, Category = "ItemDatabase") FORCEINLINE UTexture2D * GetItemIconTexture(const FGameplayTag & ItemNameTag) const; 

BlueprintCallable仅表示可以在Blueprint中使用此函数。 如果您阅读了上一篇文章 ,您可能会注意到调用此属性的其他功能没有。 之所以这样做,是因为Blueprint中当前不需要他们调用的数据。 如果某人不需要了解某些信息,我们不急于举报。


下一步是在我们创建的数据库的任何蓝图类型中创建一个变量(在我的情况下,它是BP_DreampaxItemsDataAsset )。


之后,我们可以轻松地提取分配的纹理。




现在考虑如何使用C ++访问信息。
我们不能简单地引用DreampaxItemsDataAsset类,因为它不包含任何信息。 我们需要访问BP_DreampaxItemsDataAsset


获得Blueprint的主要方法有两种。
首先,考虑使用ConstructorHelpers拐杖的不便连接方法。 在这种情况下,访问纹理。


 ASHUD::ASHUD(const class FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { /* You can use the FObjectFinder in C++ to reference content directly in code. Although it's advisable to avoid this and instead assign content through Blueprint child classes. */ static ConstructorHelpers::FObjectFinder<UTexture2D> HUDCenterDotObj(TEXT("/Game/UI/HUD/T_CenterDot_M.T_CenterDot_M")); CenterDotIcon = UCanvas::MakeIcon(HUDCenterDotObj.Object); } 

该示例取材于精彩的EpicSurvivalGameSeries项目,该项目非常适合学习C ++中的 Multiplayer 。 作者设定了一个目标,以显示尽可能多的C ++游戏编程方法和技术。


为什么这种方法不方便? 与DataTable一样的麻烦-如果更改了蓝图名称或位置,将找不到该文件。


最可取的方法是一种方法,在该方法中,我们在头文件中声明一个变量,以供已在继承的Blueprint中进行后续分配。 对于上面的示例,它可能看起来像这样:


  UPROPERTY(EditDefaultsOnly, Category = "AimPointer") FCanvasIcon CenterDotIcon; 

容易得多,对吗?
纹理分配



现在,知道了如何访问任何Blueprint ,我们可以轻松地连接数据库。


 UCLASS() class ADreampaxGameMode : public AGameMode { GENERATED_BODY() public: ADreampaxGameMode(const FObjectInitializer & ObjectInitializer); ///////////////////////////////////////////////////////////////////////////// //Data Bases ///////////////////////////////////////////////////////////////////////////// public: /* Connect data base in BP for items*/ UPROPERTY(EditDefaultsOnly, Category = "Database") class UDreampaxItemsDataAsset * DreampaxItemsDataAsset; FORCEINLINE UDreampaxItemsDataAsset * GetDreampaxItemsDataAsset() const; 

对于非专业人士来说,声明变量要小题大做

作为一个几乎不熟悉C ++的人 ,我打破了很多副本,试图弄清楚如何正确声明自定义变量。


如果目标是声明我们创建的类的变量,例如


 UDreampaxItemsDataAsset * DreampaxItemsDataAsset; //  class UDreampaxItemsDataAsset * DreampaxItemsDataAsset; 

我个人一段时间不了解何时使用该类 ,何时不使用。


事实证明一切都很简单。


  1. 如果未设置该类 ,则需要包含#include“ Data / DreampaxItemsDataAsset.h” ,其中包含此类的声明。
  2. 如果设置了 ,则可以在.cpp中完成#include“ Data / DreampaxItemsDataAsset.h”
  3. 如果需要一次声明此类的多个变量,则还有上一段的另一个选项。 毕竟#include之后,立即声明我们的类UDreampaxItemsDataAsset; ,然后声明不带前缀的变量。

这些方法中的哪一种是正确的-我不能说。 如果有人解释,我将不胜感激。


我们在C ++ADreampaxGameMode中创建一个变量,因为它仅对服务器可见,并且与对象生成相关的所有事物都应仅通过服务器。 此类是BP_DreampaxGameGame的父 ,在此我们插入BP_DreampaxItemsDataAsset


BP_DreampaxItemsDataAsset连接
BP_DreampaxItemsDataAsset连接

现在, C ++的所有功能都可以用于处理我们数据库的数据。


在下一篇文章 (最后!)中,我们将讨论创建清单并找出为什么没有已经创建的DataAsset就无法做到的事情


如果您有疑问或建议要更详细地披露任何方面,请在评论中写。

Source: https://habr.com/ru/post/zh-CN418951/


All Articles