[UE4] Blueprint実装をC++実装にする際のヒント

検証バージョン：UE4.27
# 概要
　Blueprintでノードを使って実装はできるけどC++ではどのように実装すればよいか分からないことがあるかと思います。そのようなケースでは、UE4の[ネイティブ化](https://docs.unrealengine.com/4.27/ja/ProgrammingAndScripting/Blueprints/TechnicalGuide/NativizingBlueprints/)の機能を利用することによって参考にするコードを作成することができます。

　実際には [APIリファレンス](https://docs.unrealengine.com/4.27/en-US/API/)を見るか、サンプルプロジェクトやエンジンコードの実装を参考にするのがベターで分かりやすいです。

# 手順
####① Blueprintの用意
　実装したい内容を作成するためにBlueprintを用意します。ここでは例として**BP_TestActor**を用意します。
![2021-11-10_01h36_28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/7a3ec8a6-a54f-8fed-c1a5-bd7eeffe6e61.png)

####② Blueprintの実装
　Blueprintで実装したい内容をノードで作成します。ここでは例としてSpawnActorを作成します。
![2021-11-10_01h33_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/1a84a0c3-3d38-d51b-ebdf-7e115790ca46.png)

####③ ネイティブ化の設定
　先ほど作成したBlueprintをProject SettingsのNativizeの項目から設定します。ここでは先ほど作成したBlueprintのみを対象とするために、BlueprintNativizeMethodを**Exclusive**と設定し、ListOfBlueprintAssetsToNativizeに**BP_TestActor**を指定します。
![2021-11-10_01h33_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/bf6e84ed-5ec2-471f-fb6d-55ee929b9967.png)

####④ プロジェクトのパッケージ
　プロジェクトのパッケージングを行います。パッケージングが完了すると、以下のパスに先ほどのBlueprintがネイティブ化されたコードが作成されます。

**【ネイティブ化コード出力先】**
[Project]\Intermediate\Plugins\NativizedAssets\Windows\Game\Source\NativizedAssets\Private

 以下のように.cppファイルが出力されていることを確認できます。
![2021-11-10_01h37_48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/6d45f64b-f16c-07c6-ca15-32ec8cf27803.png)

####⑤ 出力されたコードを確認
　先ほどのコードを見てみると、視覚的には少し分かりにくいですがネイティブ化されたコードを見ることができます。SpawnActorのコードを探してみると以下の部分がそれに該当します。このコードを見ることで、C++では [UGameplayStatics::BeginDeferredActorSpawnFromClass](https://docs.unrealengine.com/4.27/en-US/API/Runtime/Engine/Kismet/UGameplayStatics/BeginDeferredActorSpawnFromClass/)を利用すれが実現することが分かります。

```cpp:
void ABP_TestActor_C__pf3387606903::bpf__ExecuteUbergraph_BP_TestActor__pf_0(int32 bpp__EntryPoint__pf)
{
	FTransform bpfv__CallFunc_MakeTransform_ReturnValue__pf{};
	AActor* bpfv__CallFunc_BeginDeferredActorSpawnFromClass_ReturnValue__pf{};
	AActor* bpfv__CallFunc_FinishSpawningActor_ReturnValue__pf{};
	check(bpp__EntryPoint__pf == 3);
	// optimized KCST_UnconditionalGoto
	bpfv__CallFunc_MakeTransform_ReturnValue__pf = UKismetMathLibrary::MakeTransform(FVector(0.000000,0.000000,0.000000), FRotator(0.000000,0.000000,0.000000), FVector(1.000000,1.000000,1.000000));
	bpfv__CallFunc_BeginDeferredActorSpawnFromClass_ReturnValue__pf = UGameplayStatics::BeginDeferredActorSpawnFromClass(this, AActor::StaticClass(), bpfv__CallFunc_MakeTransform_ReturnValue__pf, ESpawnActorCollisionHandlingMethod::Undefined, ((AActor*)nullptr));
	bpfv__CallFunc_MakeTransform_ReturnValue__pf = UKismetMathLibrary::MakeTransform(FVector(0.000000,0.000000,0.000000), FRotator(0.000000,0.000000,0.000000), FVector(1.000000,1.000000,1.000000));
	bpfv__CallFunc_FinishSpawningActor_ReturnValue__pf = UGameplayStatics::FinishSpawningActor(bpfv__CallFunc_BeginDeferredActorSpawnFromClass_ReturnValue__pf, bpfv__CallFunc_MakeTransform_ReturnValue__pf);
	return; // KCST_GotoReturn
}
```

# まとめ
 上記のコードはあくまでネイティブ化されたコードのため、実際にはもっとアクセスしやすかったり使いやすい関数があるかもしれません。しかしながら既存機能を利用することによってこのように逆引きできるということも覚えておくと良いです。ちなみにこのコードはパッケージとして動作させる際にVisualStudioを利用してデバッグもできるので、ネイティブ化機能を利用した際のデバッグにも利用できます。