Створення свого типу ассета в Unreal Engine 4 і кастомізація панелі властивостей



Мене звуть Дмитро. Я займаюся створенням комп'ютерних ігор Unreal Engine в якості хобі. Сьогодні я хотів би розповісти як в Unreal Engine створити свій тип ассета і як додати додатковий елемент на панель властивостей ассета. Отже почнемо.

Почнемо з створення ассета. По перше треба створити клас для свого ассета.

UCLASS()
class UICUSTOM_API UMyObject : public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, Category = "My Object Properties")
FString Name;

};

Після цього потрібно щоб наш ассет відображався в контент браузері для цього створюємо нащадка для класу UFactory:

UCLASS()
class UICUSTOM_API UMyObjectFactory : public UFactory
{
GENERATED_UCLASS_BODY()

// UFactory interface
virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
// End of interface UFactory
віртуальний bool CanCreateNew() const override;
};

Тут для нас найбільш важливим методом є FactoryCreateNew який створює екземпляр нашого класу.

UObject* UMyObjectFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
{
UMyObject* NewObjectAsset = NewObject<UMyObject>(InParent,Class, Name, Flags | RF_Transactional);

return NewObjectAsset;
}

Отже наш ассет вже можна створити контент браузері але не можна вибрати не назву, не колір іконки, не категорію в кінці кінців. Для всього цього необхідно створити ще один клас, нащадок FAssetTypeActions_Base.

class UICUSTOM_API FMyObjectAssetAction : public FAssetTypeActions_Base
{
public:
virtual FText GetName() const override;
virtual FColor GetTypeColor() const override;
virtual UClass* GetSupportedClass() const override;
віртуальний bool HasActions(const TArray<UObject*>& InObjects) const override { return false; }
virtual uint32 GetCategories() override;
static void RegistrateCustomPartAssetType();
};

У прінцепе все зрозуміло з назви методів крім методу RegistrateCustomPartAssetType(). Цей метод потрібен для реєстрації даного класу. Отже звідки ж його викликати? Цей метод повинен бути викликаний один раз при завантаженні редактора, тому найбільш підходяще місце для його виклику це конструктор GameMode. Ось власне і він:

AUICustomGameMode::AUICustomGameMode()
{
#if WITH_EDITORONLY_DATA
FMyClassDetails::RegestrateCostumization();
FMyObjectAssetAction::RegistrateCustomPartAssetType();
#endif //WITH_EDITORONLY_DATA
}

Після цього можна компілювати проект і насолоджуватися результатом:



Ви напевно запитаєте. А який у цьому сенс, адже я можу точно також створити блюпринт який буде успадковувати MyObject, вийде теж саме але без геморою. Тут треба уточнити що блюпринт є класом спадкоємцем MyObject а не їм самим.

Наприклад, якщо розмістити посилання на MyObject в якому-небудь іншому ассете то створений таким чином ассет ви зможете вибрати, а блюпринт для якого цей ассет є базовим немає.



Як бачите ассет є, а блюпринта немає.

Тепер перейдемо до додавання елементів на панель властивостей ассета. Для цього створимо піддослідний клас:

UCLASS()
class UICUSTOM_API ATestAct : public AActor
{
GENERATED_BODY()

public: 
// Sets default values for this actor's properties
ATestAct();

// Called when the game starts or when spawned
virtual void BeginPlay() override;

// Called every frame
virtual void Tick( float DeltaSeconds ) override;

UPROPERTY(EditAnywhere, BlueprintReadWrite)
UMyObject* MyObject;

};

Що б кастомизировать його панель властивостей потрібно створити клас спадкоємець IDetailCustomization:

class FMyClassDetails : public IDetailCustomization
{
public:
static FReply MClick(IDetailLayoutBuilder* DetailBuilder);

/** Makes a new instance of this detail layout class for a specific detail view requesting it */
static TSharedRef<IDetailCustomization> MakeInstance();

static void RegestrateCostumization();

/** IDetailCustomization interface */
virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override;

static void ShowNotification(FText Text, SNotificationItem::ECompletionState State = SNotificationItem::CS_None);

static ATestAct* GetObject(IDetailLayoutBuilder* DetailBuilder);
};

Отже роз'яснюю: MClick метод, який спрацює коли ми натиснемо на додану кнопку (в якості прикладу я вибрав команду, але це може бути будь-який елемент інтерфейсу).

CustomizeDetails метод в якому відбувається додавання нового елемента на панель деталей:

void FMyClassDetails::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
{
// Create a category so this is displayed early in the properties
ATestAct* TestAct = GetObject(&DetailBuilder);
IDetailCategoryBuilder& MyCategory = DetailBuilder.EditCategory("Button", FText::GetEmpty(), ECategoryPriority::Important);

//You can get properties using the detailbuilder
//MyProperty= DetailBuilder.GetProperty(GET_MEMBER_NAME_CHECKED(MyClass, MyClassPropertyName));

FText TestHUDText = FText::FromString("Your Text");
MyCategory.AddCustomRow(TestHUDText)
.ValueContent() //NameContent()
[
SNew(SButton)
.Text(FText::FromString("ShowMessage"))
.OnClicked(FOnClicked::CreateStatic(&FMyClassDetails::MClick, &DetailBuilder))
];

}

RegestrateCostumization Метод необхідний для реєстрації даної кастомізації. (Ви напевно помітили його виклик конструктора GameMode) хочеться відзначити що TestAct потрібно вводити без префікса A:

void FMyClassDetails::RegestrateCostumization()
{
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");

//Custom detail views
PropertyModule.RegisterCustomClassLayout("TestAct", FOnGetDetailCustomizationInstance::CreateStatic(&FMyClassDetails::MakeInstance));
}

ShowNotification Просто виводить повідомлення на екран. GetObject Дозволяє отримати посилання на кастомизируемый об'єкт (ATestAct в даному випадку).

Отже, ось що ми маємо в результаті:



Спасибі за увагу, сподіваюся, цей урок дозволить вам створювати ще більш кращі і цікаві ігри. Проект з вихідними кодами можна скачати тут.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.