johnnyGameStudio’s blog

無能なゲームプログラマのぼやき ぎーくになりたい Twitter: https://twitter.com/JGS_Developer

【UE4】ランライムに生成されるActorComponent内のMesh情報をエディタ上で表示する

はじめに

開発していると「このMeshは動的に入れ替わるからエディタ上ではまだ生成されていないし、デフォルトで余計なMeshは表示させたくない」といったクラス設計にすることが多々あると思います
しかしまだ動的に生成されるオブジェクトはそのままだとエディタ上で確認できず「このMeshはどれくらい大きいのか?比較できない」といった状況になります
その際の対処法をまとめておきます

結論:OnRegisterを使おう

実装

今回のサンプルの構造としてはUTestComponentを持つATestActorを継承したBPクラスを作成し、ATestCharactorをB;ueprintエディタ上で設定します

ATestActorとATestCharactorは特筆することはないのでてきとーに用意してください

ざっくり以下のような図になります
image.png

確認

エディタで確認すると表示しているのはATestActorを継承したBlueprintですが、設定してATestCharacotrが表示されていることがわかるとおもいます(椅子のMeshがATestCharacotr)

image.png
image.png

Sample Code

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Components/SceneComponent.h"
#include "TestComponent.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class SANDBOX_API UTestComponent : public USceneComponent
{
    GENERATED_BODY()

public: 
    // Sets default values for this component's properties
    UTestComponent();

protected:
    // Called when the game starts
    virtual void BeginPlay() override;
    virtual void OnRegister() override;
    virtual void OnUnregister() override;

public: 
    // Called every frame
    virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

    void CreateCharactor();
    void DestroyCharactor();

private:
    UPROPERTY(EditAnywhere)
    TSubclassOf<class ATestCharactor> charactorClass;
    UPROPERTY()
    class ATestCharactor* meshActor = nullptr;
    UPROPERTY()
    bool bCreatedCharactor = false;
        
};
// Fill out your copyright notice in the Description page of Project Settings.


#include "TestComponent.h"
#include "Engine/World.h"
#include "TestCharactor.h"

// Sets default values for this component's properties
UTestComponent::UTestComponent()
{
    // Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
    // off to improve performance if you don't need them.
    PrimaryComponentTick.bCanEverTick = true;

    // ...
}
void UTestComponent::OnRegister()
{
    Super::OnRegister();
    CreateCharactor();
}
void UTestComponent::OnUnregister()
{
    DestroyCharactor();
    Super::OnUnregister();
}
void UTestComponent::CreateCharactor()
{
    if (charactorClass != nullptr)
    {
        DestroyCharactor();

        FActorSpawnParameters spawnParameters;
        spawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
        meshActor = GetWorld()->SpawnActor<ATestCharactor>(charactorClass,FTransform(), spawnParameters);
        //自身の子オブジェクトとしてぶら下げる
        meshActor->AttachToComponent(this,FAttachmentTransformRules::KeepRelativeTransform);
    }
}
void UTestComponent::DestroyCharactor()
{
    if (meshActor != nullptr)
    {
        meshActor->Destroy();
        meshActor = nullptr;
    }
}
...

注意点

OnUnregisterを忘れないように

OnRegisterはPlay時に呼ばれたり、PlayInから停止して非実行状態に戻ってきたときにも再度呼ばれたりするので生成するクラスが増えてしまったりするのでOnUnregisterで生成しておいたMeshはDestroyしておくのを忘れないようにしておきましょう