zer0から始めるプログラミング生活

UE4,unityなどいろいろメモ

【Unreal C++】⑥Interface【UE4】

今回はC++とブループリントでインターフェースを呼ぶ機会があったので備忘録として。
他にもいい方法があると思うのであくまで参考程度でお願いします。
エンジンはVer4.18.3を使用しています。
ちなみにブループリントインターフェースなどインターフェースについては以下のリンクを参照してください。
docs.unrealengine.com
unrealengine.hatenablog.com


①クラスの作成&宣言

おそらくBP側で作成したインターフェースはC++側に呼ぶことが出来ないのでC++側でインターフェースを作成します。C++でインターフェースを継承したクラスを作成します。
関数指定子をBlueprintImplementableEventでもいけるという情報もありましたが、参考したサイトの多くがBlueprintNativeEventを使用していたのでこちらを使用します。
unreallife.hatenablog.com


hogeInterface.h

#include "CoreMinimal.h"
#include "hogeInterface.generated.h"

UINTERFACE(Blueprintable)
class hogeProject_API UhogeInterface : public UInterface
{
	GENERATED_UINTERFACE_BODY()
};


class hogeProject_API IhogeInterface
{
	GENERATED_IINTERFACE_BODY()

public:
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
		void hogeFunc();
}

hogeInterface.cpp

#include "hogeInterface.h"


UhogeInterface::UhogeInterface(const FObjectInitializer& ObjectInitializer)
	:Super(ObjectInitializer)
{
}

void IhogeInterface::hogeFunc_Implementation()
{
}

ブループリントでの実装

イベント側

「Event hogeFunc」を呼んであげます。

イベントを呼び出すためには「Class Settings→interface→Implemented Interface」に先ほど作成したhogeInterfaceを追加してコンパイルする必要があります。

呼び出し側

「hogeFunc(Message)」を呼んであげます。
Targetノードにはイテレータ、Get All Actors with Interface、Get All Widgets with Interfaceなどを用いて検索したイベント側のクラスを繋いであげます。
自分はレベルストリーミング使用しているのでGet All Widgets of Classの第2引数のTop Level Onlyはfalseにしました。

f:id:bigden:20180214202143p:plain

C++での実装

イベント側(hogeActor)

hogeInterface を継承したクラスを作成し、関数をOverrideしてあげます。

hogeActor.h

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "hogeInterface.h”
#include "hogeActor.generated.h"

UCLASS()
class hogeProject_API AApple : public AActor, public IhogeInterface
{
	GENERATED_BODY()
public:
	//Interface 
	virtual void hogeFunc_Implementation() override;
};

hogeActor.cpp

void hogeActor::hogeFunc_Implementation()
{
//処理
}

呼び出し側

検索して配列に格納してRanged-forを用いて配列に対して処理をしてあげます。

TArray<AhogeActor*>hogeActAry;
UWorld* World=GEngine->GameViewport->GetWorld();
UGameplayStatics::GetAllActorsWithInterface(World,UhogeInterface::StaticClass(),hogeActAry);
for(AhogeActor* hogeAct : hogeActAry)
{
IhogeInterface::Execute_hogeFunc(hogeAct);
}


Get All Actors of Class、Get All Widgets of Classなどは遅い処理なのでTickなどで呼ばないでください。
docs.unrealengine.com

Markdown記法

GitBucketに挙げたリポジトリWikiを書く機会があったのでMarkdown記法をメモ。はてなブログでもMarkdownで書けるみたいです。

Markdown

とりあえず、GitBucketのwikiで使えるのだけ。ほかは↓を参考にしてください。

qiita.com

見出し

# 見出し大
## 見出し中
### 見出し小

記号の後ろに半角の空白が必須。

強調

hoge

**hoge**
__hoge__ (_(アンダースコア)2つ)

リスト

* hoge
+ hoge
- hoge

上下に空白行必須。
記号の後ろに半角の空白が必須。

ハイライト(コード挿入時など)

`hoge`

打消し線

hoge

~~hoge~~

リンク

zer0から始めるプログラミング生活

[リンクテキスト](URL)

画像埋め込み

f:id:bigden:20171226213050p:plain

![テキスト](画像のURL)

左揃え 中央 右揃え

hoge

hoge

hoge

|左揃え|中央|右揃え|
|:---|:---:|---:|
|hoge|hoge|hoge|

【Unreal C++】⑤Timer(Delay)【UE4】

BPのDelayに相当する処理をするにはTimerを使うようです。
他に方法があればコメントで教えて頂けると幸いです。

Timerの開始

Timerを開始するにはFTimerManagerのSetTimer 関数を用います。

World->GetTimerManager().SetTimer(_TimerHandle,Callback,Rate,bLoop,FirstDelay);


引数 説明
_TimerHandle FTimerHandle Timerを管理する変数
Callback TFunction 呼びたい関数
Rate float 関数を何秒ごとに呼ぶか
bLoop bool ループするかどうか
FirstDelay float 最初に何秒待つか


例(カウントタイマー)

hogeActor.h

UCLASS()
class HOGEPROJECT_API AhogeActor : public AActor
{
	GENERATED_BODY()
	
public:
	// Sets default values for this actor's properties
	AhogeActor();

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

	UFUNCTION()
	void Timer();

public:
	// Called every frame
	virtual void Tick(float DeltaTime) override;

protected:
	UPROPERTY()
	UWorld* World;

public:
         UPROPERTY()
	int PlayTime;
};


hogeActor.cpp

void AhogeActor::BeginPlay()
{
World=GEngine->GameViewport->GetWorld();
FTimerHandle _TimerHandle;	
World->GetTimerManager().SetTimer(_TimerHandle, this, &AhogeActor::Timer,1.0f, true);
}

void AhogeActor::Timer()
{
PlayTime+=1;
}


Timerの停止

Timerを停止するにはFTimerManagerのClearTimer 関数を用います。
また、もう一度同じTimerHadleでSetTimerを呼ぶと既存のものが破棄され、新しいものに置き換えられます。
ClearしたTimerHandleは新しいTimerを管理するために再利用することが出来ます。

World->GetTimerManager().ClearTimer(_TimerHandle);
引数 説明
_TimerHandle FTimerHandle Timerを管理する変数


Timerの一時停止

Timerによる関数呼び出しを一時的に実行しないようにするにはFTimerManagerのPauseTimer 関数を用います。

World->GetTimerManager().PauseTimer(_TimerHandle);


Timerの再開

一時停止したTimerを再開させるにはFTimerManagerのUnPauseTimer 関数を用います。

World->GetTimerManager().UnPauseTimer(SampleTimerHandle);  

Timerが一時停止状態の確認

Timerが一時停止しているかどうかを確認するためにはFTimerManagerのIsTimerPaused 関数を用います。bool値がreturnされます。

 if( World->GetTimerManager().IsTimerPaused(_TimerHandle) == true )  
{ 
}

反対にTimerがアクティブで一時停止していないことを確認するためにはFTimerManagerのIsTimerActive 関数を用います。bool値がreturnされます。

 if( World->GetTimerManager().IsTimerActive(_TimerHandle) == true )  
{ 
}

追記

(2018.01.10)

↓のドキュメントではループありのタイマーをClearTimer関数でタイマーのクリアを行っています。
これは実質、タイマーの停止も担っています。
ここで1つ疑問に思ったのが、ループなしのタイマーでは自動的に停止するのでタイマーの停止を目的としたClearTimer関数の使用は必要無くなりますが、クリアを目的としたClearTimerが必要なのかということです。
docs.unrealengine.com

APIにはIsTimerActive関数やTimerExists関数がありますので、こちらを用いてループなしのタイマーが自動停止した後にまだタイマーが存在しているかを調べてみたいと思います。
docs.unrealengine.com

調査

いろいろ調べ方はあると思いますが、簡単な方法で実装します。
bLoopをfalseとしたSetTimer関数をBeginPlayで呼びます。
IsTimerActive関数やTimerExists関数をTickで呼びます。


TimerAct.h

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Engine.h"
#include "TimerAct.generated.h"

UCLASS()
class HOGEPROJECT_API ATimerAct : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ATimerAct();

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

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

protected:
	UWorld* World;
	FTimerHandle _TimerHandle;

protected:
	UFUNCTION()
	void Process();
};

TimerAct.cpp

void ATimerAct::BeginPlay()
{
World=GEngine->GameViewport->GetWorld();
FTimerHandle _TimerHandle;	
World->GetTimerManager().SetTimer(_TimerHandle, this, &ATimerAct::HogeProcess,1.0f, false); //bLoop=false
}

void ATimerAct::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	if (World->GetTimerManager().IsTimerActive(_TimerHandle))
	{
		GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Green, "Active");
	}
	if (World->GetTimerManager().TimerExists(_TimerHandle))
	{
		GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Red, "Exist");
	}
}

void ATimerAct::HogeProcess()
{
}
結果

プレイ開始からHogeProcessが呼ばれるまでタイマーが存在し、その後は自動的にクリアされ、存在しなくなっているようです。


※何か間違えがあればコメントよろしくお願い致します。

【Unreal C++】④Log【UE4】

OutputLogへの出力

「ウィンドウ→デベロッパーツール→アウトプットログ」でウィンドウを出せます。

UE_LOG

UE_LOG(CategoryName, Verbosity, Message);
パラメータ 説明
CategoryName カテゴリ名(カテゴリを自作することも可能、デフォルトはLogTemp)
Verbosity ログレベル(種類)
Message メッセージ



「CategoryName」の自作方法

①ヘッダファイルでDECLARE_LOG_CATEGORY_EXTERN マクロを用いてカテゴリを宣言

DECLARE_LOG_CATEGORY_EXTERN(NewCategoryName, Log, All);

第1引数はカテゴリ名、第2引数はデフォルトのVerbosity、第3引数はコンパイル時で有効化するVerbosityです。


「Verbosity」の種類
Verbosity ログレベル 備考
Fatal 致命的なエラー ログ出力とともにクラッシュ。
Error エラー
Warning 警告
Display ログ(詳細度:最低) 灰色 コンソールとログファイルに出力
Log ログ(詳細度:低) 灰色 ログファイルに出力、アウトプットログに出力可
Verbose ログ(詳細度:高) 灰色 コンソールとログファイルに出力
VeryVerbose ログ(詳細度:最高) 灰色 コンソールとログファイルに出力



Message

文字列の他にフォーマット指定子(%d、%f)などを用いて変数を出力することが可能です。
その際は第4引数に変数を追加します。


Logコマンド

プレイ中に「@」キー(デフォルト)やOutputLogの「Enter Console command」の部分に以下のコマンドを打ち込むことでログカテゴリのVerbosity を変更することが出来ます。

log CategoryName Verbosity 



また、以下のコマンドで各カテゴリのVerbosity の設定を確認出来ます。

log list




画面への出力

AddOnScreenDebugMessage

BPでいうPrintStringです。

GEngine->AddOnScreenDebugMessage(Key, TimeToDisplay, Color, Message);
パラメータ 説明
Key int 同じメッセージが複数回追加されないようにするユニークなキー。一時的なものには-1
TimeToDisplay float 表示する秒数
Color FColor テキストを表示する色
Message FString 表示する文字
追記(2018.1.19)

HMDを被った状態でPrintStringによって表示された文字列を確認しようとすると、確認しづらい箇所に表示されるため位置を変更したかったのですが、ver4.18現在、PrintStringやAddOnScreenDebugMessageの表示位置は左上から変更できないようです。
OutputLogにも残るのでそちらを確認するか、どうしても別の位置に表示させたい場合にはTextRenderやUMGを用いて空間上に表示させるしかないようです。

追記(2018.1.21)

AddOnScreenDebugMessageの第4引数(Message)はFString型なので、他の型からFString型へ変換する必要があります。

変換元の型 変換元の変数 変換
int intValue FString::FromInt(intValue);
float floatValue FString::SanitizeFloat(floatValue);
FVector VectorValue VectorValue.ToString();
FVector2D Vector2DValue Vector2DValue.ToString();
FRotator RotatorValue RotatorValue.ToString();
FLinearColor LinearColorValue LinearColorValue.ToString();



【Unreal C++】③イテレータ【UE4】

今回はレベル内のActorやObjectを検索する方法を書いていきます。
BPではGet All Actors of Classを用いて検索していました。
docs.unrealengine.com

下準備

検索元をhoge、検索先のActorをhogeActorという名前でC++クラスを作成します。
例としてhogeActorのStaticMeshComponentの位置を取得してみたいと思います。
hoge.h

#include "CoreMinimal.h"
#include "hoge.generated.h"

UCLASS()
class HOGEPROJECT_API hoge : public AActor
{
GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	hoge();

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

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

protected:
	UPROPERTY(EditAnywhere)
		USceneComponent*Scene;
	
         UPROPERTY(EditAnywhere)
		UStaticMeshComponent* StaticMesh;
};

.cpp

#include "hoge.h"

//Set default values
hoge::hoge()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
        
        Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
	RootComponent = Scene;
        StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
	StaticMesh->SetupAttachment(RootComponent);

	
}

hogeActor.h

#include "CoreMinimal.h"
#include "hogeActor.generated.h"

UCLASS()
class HOGEPROJECT_API hogeActor : public AActor
{
GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	hogeActor();

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

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;
};

hogeActor.cpp

#include "hogeActor.h"

//Set default values
hogeActor::hogeActor()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
}

Iterators

UE4イテレータにはActorIteratorとObjectIteratorがあります。

ActorIterator


hoge.h

#include "CoreMinimal.h"
#include "EngineUtils.h" //TActorIterator
#include "hoge.generated.h"

UCLASS()
class HOGEPROJECT_API hoge: public AActor
{
GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	hogeActor();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
  
        UPROPERTY()
       UWorld* World;

        UPROPERTY()
        AhogeActor* hogeAct;

       UPROPERTY()
       FVector Loc;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;
};

TActorIteratorを使用するためにEngineUtils.hをインクルードします。
UWorld型とAhogeActor型とFVector型の変数を宣言します。


hoge.cpp

// Called when the game starts or when spawned
void Ahoge::BeginPlay()
{
	Super::BeginPlay();
	
	World = GEngine->GameViewport->GetWorld();

	for (TActorIterator<AhogeActor>hogeActorItr(World); hogeActorItr; ++hogeActorItr)
	{
		hogeAct = *hogeActorItr;
                Loc=hogeAct->StaticMesh->GetComponentLocation();
	}
}

GetWorld()でビューポート内のコンテンツを返します。
よく World=GetWorld(); だけなのを見ますが、
ver4.18現在では GEngine->GameViewport->GetWorld(); でないとダメみたいです。

BeginPlay時にWorld内に存在していれば、ヘッダファイルで宣言し、BeginPlayで検索することによって使い回せます。

	for (TActorIterator<AhogeActor>hogeActorItr(World); hogeActorItr; ++hogeActorItr)
	{
	AhogeActor* hogeAct = *hogeActorItr;
	}

のようにするとfor文の間でしか使えないので注意です。

ObjectIterator

使い方はActorIteratorと同様です。

for ( TObjectIterator<UStaticMeshComponent> Itr; Itr; ++Itr )
{
	// Access the subclass instance with the * or -> operators.
	UStaticMeshComponent *StaticMesh = *Itr;

}

配列要素のイタレーション

EpicさんのおすすめはC++のranged-for機能を使う方法だそうです。
↓ではFstringの場合ですが、Actorの配列でも同様に出来ましたのでそちらで書いていきます。
Unreal Engine | TArray:アンリアル エンジンの配列

TArray<AActor*>ActArray;
for(auto& act:ActArray)
{
act->/* do something*/
}

範囲をループして、actという変数にActArrayの各要素を自動的に代入します。
autoを使うことで変数の型を推論してくれます。

【Unreal C++】②Overlapイベント【UE4】

今回はOverlapイベントについて書いていこうと思います。

分かりやすいようにTriggerBoxを作成し、そこに何かがオーバラップ(接触)したという例を示したいと思います。
docs.unrealengine.com

TriggerBoxの作成

TriggerBoxを親クラスにするとうまくいかなかったのでActorを親クラスにしてBoxコンポーネントを追加しました。
(TriggerBoxを親クラスにした場合のやり方を知ってる方は教えていただけると幸いです。)

hoge.h

#include "CoreMinimal.h"
#include "Components/BoxComponent.h"//UBoxComponent
#include "hoge.generated.h"


UCLASS()
class HOGEPROJECT_API hoge : public AActor
{
GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	hoge();

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

	UPROPERTY()
		USceneComponent* Scene;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		UBoxComponent* BoxComp;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;


};

UBoxComponentを使用するにはBoxComponent.hをインクルードする必要があります。
ヘッダファイルの場所は(エンジンをインストールしたフォルダ)/Engine/Source/Runtime/Engine/Classes/Components/BoxComponent.hです。


.cpp

#include "hoge.h"

//Set default values
hoge::hoge()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
	RootComponent = Scene;
	BoxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionComp"));
	BoxComp->SetupAttachment(RootComponent);
}

Overlapイベント

OnComponentBeginOverlap

このイベントは対象のコンポーネントに何かがOverlap(接触する)と実行されます。
BPでは↓のようなノードです。
f:id:bigden:20171116225714p:plain

hoge.h

//OnComponentBeginOverlap
	UFUNCTION()
		void OnOverlapBegin(UPrimitiveComponent* OverlappedComponent,AActor* OtherActor,UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult);

OnOverlapBegin関数を追加し、Overlapした際に実行したいイベントを書いていきます。
ちなみにUFUNCTION()がないとクラッシュします。

hoge.cpp

hoge::hoge()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
	RootComponent = Scene;
	BoxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionComp"));
	BoxComp->SetupAttachment(RootComponent);
        //↓追加
        BoxComp->OnComponentBeginOverlap.AddDynamic(this, &Ahoge::OnOverlapBegin);
}

void Ahoge::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent,AActor* OtherActor,UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult)
{
//Overlapした際に実行したいイベント
}

AddDynamicによってOnComponentBeginOverlapと呼びたい関数をバインディングします。
これによってOverlapするとOnOverlapBeginが呼ばれます。

docs.unrealengine.com

OnComponentEndOverlap

このイベントは対象のコンポーネントへのOverlapが終了すると実行されます。
BPでは↓のようなノードです。
f:id:bigden:20171117003654p:plain

基本的にはOnComponentBeginOverlapと実装方法は同じだと思います。
Overlapした際に実行したいイベントを書く関数の引数を次のように変更します。

OnComponentOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

OnActorBeginOverlap

このイベントは対象のActorに何かがOverlapすると実行されます。
BPでは↓のようなノードです。
f:id:bigden:20171117002843p:plain

基本的にはOnComponentBeginOverlapと実装方法は同じだと思います。
Overlapした際に実行したいイベントを書く関数の引数を次のように変更します。

OnActorOverlapBegin(AActor* OverlappedActor, AActor* OtherActor);

OnActorEndOverlap

このイベントは対象のActorへのOverlapが終了すると実行されます。
BPでは↓のようなノードです。
f:id:bigden:20171117003343p:plain

基本的にはOnComponentBeginOverlapと実装方法は同じだと思います。
Overlapした際に実行したいイベントを書く関数の引数を次のように変更します。

OnActorOverlapEnd(AActor* OverlappedActor, AActor* OtherActor);

【Unreal C++】①C++クラス作成&Component追加【UE4】

だいぶUnreal C++に慣れてきたので、備忘録として書いていこうと思います。
ver4.18を使用しています。

C++クラス作成

新しいC++クラスの追加は「コンテンツブラウザの新規追加→新しいC++クラスを追加→親クラスを選択→名前をつける→クラスを作成」で作成できます。

親クラスにActorを選択し、hogeActorと名前をつけました。

hoge.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "hogeActor.generated.h"

UCLASS()
class hogeProject_API AhogeActor : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AhogeActor();

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

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

};

以上のコードは作成時に自動的に書いてくれています。

ちなみにver4.15からの仕様変更でCoreMinimal.hのincludeが必須に
詳しくは↓
miyahuji111.hatenablog.com


.cpp

#include "hogeActor.h"


// Sets default values
AhogeActor::AhogeActor()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	
}

// Called when the game starts or when spawned
void AhogeActor::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AhogeActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

cppの方も以上のコードが作成時に自動的に書いてくれています。

PrimaryActorTick.bCanEverTick をtrueにしておくと、Tick処理が呼び出されます。
必要ないときはfalseにしておいたほうが高速に動くようです。

コンポーネントはコンストラクタに書いていきます。
*BeginPlayなど他の場所に書くとクラッシュします。(error吐いてほしい...)

Component追加

.h

UPROPERTY(EditAnywhere)
USceneComponent* Scene;

UFUNCTION()
void hogeFunc();

UPROPERTY()は変数のオプションを指定できます。

オプション 説明
EditAnywhere エディタ(BP,Level)内で編集○
VisibleAnywhere エディタ内で表示○、編集☓
BlueprintReadWrite BPで読み取り○、変更○
BlueprintReadOnly BPで読み取り○、変更☓
Category=" " カテゴリを指定

他にもありますが、とりあえず良く使いそうなものだけ。

.cpp

Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
RootComponent = Scene;
Widget = CreateDefaultSubobject<UWidgetComponent>(TEXT("Widget"));
Widget->SetupAttachment(RootComponent);
WidgetInteraction = CreateDefaultSubobject<UWidgetInteractionComponent>(TEXT("WidgetInteraction"));
Widget->SetupAttachment(RootComponent);

CreateDefaultSubobjectでコンポーネントを作成します。<>内はクラス名。TEXT内の("")はエディタ内で表示される名前です。
RootComponentで最上層のコンポーネントに設定します。
SetupAttachment(hoge)でhogeの下の層に設定します。

何か間違っていることがあればご指摘頂けると幸いです。