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

  • Tutorial

GamemodeIn 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 the 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.

    /* 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 we created (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 , ideal 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.

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

A small digression for non-pros on variable declarations.

Как человек почти незнакомый с C++, я сломал немало копий, пытаясь понять как правильно объявлять кастомные переменные.

Если стоит цель объявить переменную созданного нами класса, как, например

UDreampaxItemsDataAsset * DreampaxItemsDataAsset;
// илиclassUDreampaxItemsDataAsset * DreampaxItemsDataAsset;

лично мне какое-то время было непонятно когда нужно применять class, а когда нет.

Все оказалось до боли просто.

  1. Если не ставить class, то нужно выполнить включение #include "Data/DreampaxItemsDataAsset.h", содержащее объявление этого класса.
  2. Если ставить class, то #include "Data/DreampaxItemsDataAsset.h" можно сделать уже в .cpp.
  3. И еще одна опция предыдущего пункта, если нужно объявить сразу много переменных данного класса. Непосредственно после всех #include предварительно объявить наш класс class UDreampaxItemsDataAsset;, а после объявлять переменные уже без приставки class.

Какой из этих способов правильный — не берусь сказать. Если кто-то объяснит, буду благодарен.

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
Подключение 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.

Also popular now: