はじめに
C++で作成したActorに自分で追加してあるActorComponentのメンバ変数をLevelSequenceで扱いたい場合の手順がまとまっている情報がなかったので備忘録を兼ねてまとめておきます
環境
UE4.24.2
VisualStudioCommunity2017
Windows10
HowTo
ActorのコンストラクタでActorComponentを追加する
たとえ、メンバ変数にActorComponentを持っていたとしてもコンストラクタでCreateDefaultSubobjectで追加しておかないとLevelSequenceで認識してくれません
検証用に以下のサンプルでは二つのActorComponentを
- コンストラクタでインスタンスを生成する
- BeginPlayでインスタンスを生成する
という二つの方法でやってみます
// 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++そのものにリフレクションはないので考えてみれば当たり前ですね