Розробка

UE4 | Інвентар для Multiplayer #2 | Підключення Blueprint до C++

Список статей

UE4 | Інвентар для Multiplayer #1 | Сховище даних на DataAsset
UE4 | Інвентар для Multiplayer #2 | Підключення Blueprint до C++
UE4 | Інвентар для Multiplayer #3 | Структура взаємодії

У попередній статті я розповідав як створити DataAsset, і чому він такий хороший і зручний. Тут же ми розглянемо те, як отримати доступ до DataAsset, точніше до призначених у ньому даними, з Blueprint і C++.

Попутно ми відповімо на питання отримання доступу до будь-якого Blueprint з C++.

Із взаємодією Blueprints все досить прозоро.
Зважаючи на те, що ми закрили прямий доступ до нашої бази даних, ми не можемо просто так звернеться до неї з Blueprint. Зверніть увагу на protected: у коді нижче.

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 не знадобилися. Якщо комусь щось знати не потрібно — не поспішаємо про це повідомляти.

Наступний крок, це створення у кожному Blueprint змінної типу створеної нами бази даних (в моєму випадку це BP_DreampaxItemsDataAsset).

Після цього легко невимушено витягаємо призначену текстуру.

Тепер розглянемо як отримати доступ до інформації в C++.
Ми не можемо просто звернутися до класу DreampaxItemsDataAsset, оскільки він не містить ніякої інформації. Нам потрібно отримати доступ до BP_DreampaxItemsDataAsset.

Існує два основних метода як достукатися до Blueprint.
Спочатку розглянемо незручний спосіб підключення з використанням милиці ConstructorHelpers. В даному випадку це доступ до текстурою.

ASHUD::ASHUD(const class FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
 /* You can use the FObjectFinder in C++ reference to 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, ідеально відповідного для вивчення Multiplayer на C++. Автор поставив за мету показати якомога більше методів та прийомів програмування гри на C++.

Чому цей спосіб незручний? Та ж біда як і з DataTable — при зміні назви Blueprint або місця розташування, файл не знайдений.

Найкращим можна вважати метод в якому ми оголошуємо змінну в заголовочном файлі, для подальшого призначення її вже в наследованном 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;

особисто мені якийсь час було незрозуміло коли потрібно застосовувати class, а коли ні.

Все виявилося до болю просто.

  1. Якщо не ставити class, то потрібно виконати включення #include “Data/DreampaxItemsDataAsset.h”, що містить оголошення цього класу.
  2. Якщо ставити class, то #include “Data/DreampaxItemsDataAsset.h” можна зробити уже .cpp.
  3. І ще одна опція попереднього пункту, якщо потрібно оголосити відразу багато змінних даного класу. Безпосередньо після усіх #include попередньо оголосити наш клас class UDreampaxItemsDataAsset;, а після оголошувати змінні вже без приставки class.

Який з цих способів правильний — не беруся сказати. Якщо хтось пояснить, буду вдячний.

Робимо змінну C++ класі ADreampaxGameMode, так як він видно тільки сервера, а все що пов’язано зі спауном об’єктів повинно йти тільки через сервер. Даний клас є батьком для BP_DreampaxGameMode, де ми підключимо наш BP_DreampaxItemsDataAsset.

Підключення BP_DreampaxItemsDataAsset

Тепер вся міць C++ може бути використана для роботи з даними нашої бази даних.

У наступній статті (нарешті!) ми поговоримо про створення інвентарю і дізнаємося чому нам ніяк не обійтися без вже створеного DataAsset.

Якщо є питання або побажання розкрити будь-який аспект детальніше, будь ласка пишіть в коментарях.

Related Articles

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *

Close