【UE4】LevelSequenceでActorComponentを継承したComponentのプロパティを扱いたい
はじめに
C++で作成したActorに自分で追加してあるActorComponentのメンバ変数をLevelSequenceで扱いたい場合の手順がまとまっている情報がなかったので備忘録を兼ねてまとめておきます
環境
UE4.24.2
VisualStudioCommunity2017
Windows10
HowTo
ActorのコンストラクタでActorComponentを追加する
たとえ、メンバ変数にActorComponentを持っていたとしてもコンストラクタでCreateDefaultSubobjectで追加しておかないとLevelSequenceで認識してくれません
検証用に以下のサンプルでは二つのActorComponentを
という二つの方法でやってみます
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "TestActor.generated.h" UCLASS() class TESTPRJ_API ATestActor : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties ATestActor(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; private: class UTestComponent* testComp;//コンストラクタで生成 class UTestComponent* testComp2;//BeginPlayで生成 };
// Fill out your copyright notice in the Description page of Project Settings. #include "TestActor.h" #include "TestComponent.h" // Sets default values ATestActor::ATestActor() { // 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; testComp = CreateDefaultSubobject<UTestComponent>(TEXT("testComp")); } // Called when the game starts or when spawned void ATestActor::BeginPlay() { Super::BeginPlay(); testComp2 = NewObject<UTestComponent>(this); testComp2->RegisterComponent(); }
LevelSequenceで扱いたいメンバ変数にUPROPERTY(Interp)を付与する
LevelSequenceでメンバ変数を直接変更させる場合、UPROPERTY(Interp)をつけてあげる必要があります
なので今回はてきとーにBoolの変数をActorComponentに追加しました
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Components/ActorComponent.h" #include "TestComponent.generated.h" UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) class TESTPRJ_API UTestComponent : public UActorComponent { GENERATED_BODY() public: // Sets default values for this component's properties UTestComponent(); protected: // Called when the game starts virtual void BeginPlay() override; public: // Called every frame virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; private: UPROPERTY(Interp)//追加 bool bFlag; };
確認
てきとーなLevelSequenceを作成し、TestActorのトラックを追加してみるとコンストラクタで追加した「testComp」だけが表示されて「testComp2」は表示されないことがわかります
また、TestComponentのメンバ変数がLevelSequenceのトラックとして追加できるようになっていることが確認できます
なぜコンストラクタで追加しないとLevelSequenceで扱えないのか
コンストラクタ内にブレイクポイントを仕込むとわかるのですが、UObjectを継承しているクラスのコンストラクタは以下の二つのタイミングで実行されます
- ゲームが実行されたとき
- エディタを起動するとき
つまり、エディタを起動する際にUObjectのリフレクション情報を生成しておいて、その情報を以ってLevelSequenceで扱えるようにしているわけです
C++そのものにリフレクションはないので考えてみれば当たり前ですね