zer0から始めるプログラミング生活

unreal EngineやUnityのTipsを書いていきます。

【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を使うことで変数の型を推論してくれます。