📜 ⬆️ ⬇️

UE4 | Inventory for Multiplayer # 2 | Connect Blueprint to C ++




Gamemode In the previous article, I explained how to create DataAsset , and why it is so good and convenient. Here we will look at how to access DataAsset , more precisely, the data assigned to it, from Blueprint and C ++ .


Along the way, we will answer the question of accessing any Blueprint from C ++ .




With the interaction of Blueprints, everything is quite transparent.
Due to the fact that we have closed direct access to our database, we cannot simply access it from Blueprint . Pay attention to protected: in the code below.


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

Those. our storage will be visible only in inherited classes, and this is good, because we have prescribed functions for safe data call.


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

BlueprintCallable just means that this function can be used in Blueprint . If you read the previous article , you probably noticed that other functions for invoking such an attribute do not have. This is done only because the data they are currently calling is not needed in Blueprint . If you don’t need to know something, don’t be in a hurry to report it.


The next step is to create in any Blueprint a variable of the type of the database created by us (in my case, this is BP_DreampaxItemsDataAsset ).


After that, it is easy to easily remove the assigned texture.




Now consider how to access information in C ++ .
We cannot simply refer to the DreampaxItemsDataAsset class, since it does not contain any information. We need to get access to BP_DreampaxItemsDataAsset .


There are two main methods of how to reach Blueprint .
First, consider the inconvenient way to connect using the ConstructorHelpers crutch. In this case, it is access to the texture.


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

The example is taken from the wonderful EpicSurvivalGameSeries project, ideally suited for learning Multiplayer in C ++ . The author has set a goal to show as many methods and techniques of game programming in C ++ as possible.


Why is this method uncomfortable? The same trouble as with DataTable - if you change the name of the Blueprint or location, the file will not be found.


The most preferable is the method in which we declare a variable in the header file, for later assignment in the inherited Blueprint . For the example above, this might look like this:


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

Much easier, right?
Texture assignment



Now, knowing how to access any Blueprint , we can easily connect our database.


 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; 

A small digression for non-pros on variable declarations.

As a person almost unfamiliar with C ++ , I broke a lot of copies, trying to figure out how to correctly declare custom variables.


If the goal is to declare a variable of the class created by us, such as


 UDreampaxItemsDataAsset * DreampaxItemsDataAsset; //  class UDreampaxItemsDataAsset * DreampaxItemsDataAsset; 

for me personally, for some time, it was not clear when it is necessary to apply a class , and when not.


Everything turned out to be painfully simple.


  1. If you do not set the class , then you need to include the #include "Data / DreampaxItemsDataAsset.h" containing the declaration of this class.
  2. If you set the class , then #include "Data / DreampaxItemsDataAsset.h" can be done already in .cpp .
  3. And one more option of the previous paragraph, if you need to declare many variables of this class at once. Immediately after all #include, pre-declare our class UDreampaxItemsDataAsset; , and after declaring variables without the prefix class .

Which of these methods is correct - I can not say. If someone explains, I will be grateful.


We make a variable in the C ++ class ADreampaxGameMode , since it is visible only to the server, and everything related to the spawn of objects must go only through the server. This class is the parent for BP_DreampaxGameMode , where we connect our BP_DreampaxItemsDataAsset .


Connection BP_DreampaxItemsDataAsset
Connection BP_DreampaxItemsDataAsset

Now all the power of C ++ can be used to work with the data of our database.


In the next article (finally!) We will talk about inventory creation and find out why we cannot do without the already created DataAsset .


If you have questions or requests to disclose any aspect in more detail, please write in the comments.


')

Source: https://habr.com/ru/post/418951/


All Articles