【Unreal C++】③イテレータ【UE4】
今回はレベル内のActorやObjectを検索する方法を書いていきます。
BPではGet All Actors of Classを用いて検索していました。
docs.unrealengine.com
下準備
検索元をhoge、検索先のActorをhogeActorという名前でC++クラスを作成します。
例としてhogeActorのStaticMeshComponentの位置を取得してみたいと思います。
hoge.h
#include "CoreMinimal.h" #include "hoge.generated.h" UCLASS() class HOGEPROJECT_API hoge : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties hoge(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; public: // Called every frame virtual void Tick(float DeltaTime) override; protected: UPROPERTY(EditAnywhere) USceneComponent*Scene; UPROPERTY(EditAnywhere) UStaticMeshComponent* StaticMesh; };
.cpp
#include "hoge.h" //Set default values hoge::hoge() { // 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; Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene")); RootComponent = Scene; StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh")); StaticMesh->SetupAttachment(RootComponent); }
hogeActor.h
#include "CoreMinimal.h" #include "hogeActor.generated.h" UCLASS() class HOGEPROJECT_API hogeActor : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties hogeActor(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; public: // Called every frame virtual void Tick(float DeltaTime) override; };
hogeActor.cpp
#include "hogeActor.h" //Set default values hogeActor::hogeActor() { // 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; }
Iterators
UE4のイテレータにはActorIteratorとObjectIteratorがあります。
ActorIterator
hoge.h
#include "CoreMinimal.h" #include "EngineUtils.h" //TActorIterator #include "hoge.generated.h" UCLASS() class HOGEPROJECT_API hoge: public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties hogeActor(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; UPROPERTY() UWorld* World; UPROPERTY() AhogeActor* hogeAct; UPROPERTY() FVector Loc; public: // Called every frame virtual void Tick(float DeltaTime) override; };
TActorIteratorを使用するためにEngineUtils.hをインクルードします。
UWorld型とAhogeActor型とFVector型の変数を宣言します。
hoge.cpp
// Called when the game starts or when spawned void Ahoge::BeginPlay() { Super::BeginPlay(); World = GEngine->GameViewport->GetWorld(); for (TActorIterator<AhogeActor>hogeActorItr(World); hogeActorItr; ++hogeActorItr) { hogeAct = *hogeActorItr; Loc=hogeAct->StaticMesh->GetComponentLocation(); } }
GetWorld()でビューポート内のコンテンツを返します。
よく World=GetWorld(); だけなのを見ますが、
ver4.18現在では GEngine->GameViewport->GetWorld(); でないとダメみたいです。
BeginPlay時にWorld内に存在していれば、ヘッダファイルで宣言し、BeginPlayで検索することによって使い回せます。
for (TActorIterator<AhogeActor>hogeActorItr(World); hogeActorItr; ++hogeActorItr)
{
AhogeActor* hogeAct = *hogeActorItr;
}
のようにするとfor文の間でしか使えないので注意です。
ObjectIterator
使い方はActorIteratorと同様です。
for ( TObjectIterator<UStaticMeshComponent> Itr; Itr; ++Itr ) { // Access the subclass instance with the * or -> operators. UStaticMeshComponent *StaticMesh = *Itr; }
配列要素のイタレーション
EpicさんのおすすめはC++のranged-for機能を使う方法だそうです。
↓ではFstringの場合ですが、Actorの配列でも同様に出来ましたのでそちらで書いていきます。
Unreal Engine | TArray:アンリアル エンジンの配列
TArray<AActor*>ActArray; for(auto& act:ActArray) { act->/* do something*/ }
範囲をループして、actという変数にActArrayの各要素を自動的に代入します。
autoを使うことで変数の型を推論してくれます。