うにてぃブログ

UnityやUnreal Engineの記事を書いていきます

【Unreal Engine】C++でActorクラスのコンストラクタでコンポーネントを定義せず、Blueprintで構築する方法

概要

Unreal Engineでは、C++で作成したActorクラスのコンストラクタでコンポーネントを定義するのが一般的ですが、場合によってはBlueprint Editorを使ってコンポーネントを構築したい場合があります。この記事では、C++のコンストラクタでコンポーネントを設定せずに、Blueprintでコンポーネントを設定する方法について説明します。

サンプルコードの確認

Unreal EngineのFirstPersonサンプルプロジェクトでは、Characterクラスのコンストラクタでコンポーネントが定義されています。以下はその一例です:

ABlogCharacter::ABlogCharacter()
{
    // Set size for collision capsule
    GetCapsuleComponent()->InitCapsuleSize(55.f, 96.0f);

    // Create a CameraComponent    
    FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
    FirstPersonCameraComponent->SetupAttachment(GetCapsuleComponent());
    FirstPersonCameraComponent->SetRelativeLocation(FVector(-10.f, 0.f, 60.f)); // Position the camera
    FirstPersonCameraComponent->bUsePawnControlRotation = true;

    // Create a mesh component that will be used when being viewed from a '1st person' view
    Mesh1P = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("CharacterMesh1P"));
    Mesh1P->SetOnlyOwnerSee(true);
    Mesh1P->SetupAttachment(FirstPersonCameraComponent);
    Mesh1P->bCastDynamicShadow = false;
    Mesh1P->CastShadow = false;
    Mesh1P->SetRelativeLocation(FVector(-30.f, 0.f, -150.f));
}

このように、通常はコンストラクタ内でコンポーネントを初期化しています。しかし、Unityに慣れている開発者としては、Blueprint Editorで視覚的に確認しながらコンポーネントを構築したいと考えるかもしれません。

Blueprintでコンポーネントを設定する方法

以下の手順で、コンストラクタでコンポーネントを定義せずに、Blueprintでコンポーネントを設定する方法を実装します。

.hファイルにフィールドを定義します。ここでは、コンポーネントのキャッシュを保持しますが、必要でなければ省略可能です。

Hoge.h
public:   
    UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
    TObjectPtr<USphereComponent> SphereComponentCache;

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

.cppファイルのBeginPlayメソッドで、Blueprintから設定されたコンポーネントを取得し、イベントをセットします。

Hoge.cpp
void AHoge::BeginPlay()
{
    Super::BeginPlay();

    // Blueprintで設定されたコンポーネントを取得
    SphereComponentCache = FindComponentByClass<USphereComponent>();
    
    // オーバーラップイベントをセット
    if (SphereComponentCache)
    {
        SphereComponentCache->OnComponentBeginOverlap.AddDynamic(this, &AHoge::OnOverlapBegin);
    }
}

void AActorTest::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
    UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
    UE_LOG(LogTemp, Warning, TEXT("Overlap Begin"));
}

このクラスを基にBlueprintを作成し、SphereComponentとColliderを設定します。配置後、オーバーラップイベントが発生すると、ログに「Overlap Begin」と出力されることが確認できます。

結果

このように、コンストラクタ内でコンポーネントを初期化しなくても、BeginPlayでBlueprint上のコンポーネントを取得してイベント処理を行うことが可能です。これにより、視覚的に確認しながら、Blueprint Editorでコンポーネントを構築する柔軟性が得られます。