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

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

【Unreal C++】⑤Timer(Delay)【UE4】

BPのDelayに相当する処理をするにはTimerを使うようです。
他に方法があればコメントで教えて頂けると幸いです。

Timerの開始

Timerを開始するにはFTimerManagerのSetTimer 関数を用います。

World->GetTimerManager().SetTimer(_TimerHandle,Callback,Rate,bLoop,FirstDelay);


引数 説明
_TimerHandle FTimerHandle Timerを管理する変数
Callback TFunction 呼びたい関数
Rate float 関数を何秒ごとに呼ぶか
bLoop bool ループするかどうか
FirstDelay float 最初に何秒待つか


例(カウントタイマー)

hogeActor.h

UCLASS()
class HOGEPROJECT_API AhogeActor : public AActor
{
	GENERATED_BODY()
	
public:
	// Sets default values for this actor's properties
	AhogeActor();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	UFUNCTION()
	void Timer();

public:
	// Called every frame
	virtual void Tick(float DeltaTime) override;

protected:
	UPROPERTY()
	UWorld* World;

public:
         UPROPERTY()
	int PlayTime;
};


hogeActor.cpp

void AhogeActor::BeginPlay()
{
World=GEngine->GameViewport->GetWorld();
FTimerHandle _TimerHandle;	
World->GetTimerManager().SetTimer(_TimerHandle, this, &AhogeActor::Timer,1.0f, true);
}

void AhogeActor::Timer()
{
PlayTime+=1;
}


Timerの停止

Timerを停止するにはFTimerManagerのClearTimer 関数を用います。
また、もう一度同じTimerHadleでSetTimerを呼ぶと既存のものが破棄され、新しいものに置き換えられます。
ClearしたTimerHandleは新しいTimerを管理するために再利用することが出来ます。

World->GetTimerManager().ClearTimer(_TimerHandle);
引数 説明
_TimerHandle FTimerHandle Timerを管理する変数


Timerの一時停止

Timerによる関数呼び出しを一時的に実行しないようにするにはFTimerManagerのPauseTimer 関数を用います。

World->GetTimerManager().PauseTimer(_TimerHandle);


Timerの再開

一時停止したTimerを再開させるにはFTimerManagerのUnPauseTimer 関数を用います。

World->GetTimerManager().UnPauseTimer(SampleTimerHandle);  

Timerが一時停止状態の確認

Timerが一時停止しているかどうかを確認するためにはFTimerManagerのIsTimerPaused 関数を用います。bool値がreturnされます。

 if( World->GetTimerManager().IsTimerPaused(_TimerHandle) == true )  
{ 
}

反対にTimerがアクティブで一時停止していないことを確認するためにはFTimerManagerのIsTimerActive 関数を用います。bool値がreturnされます。

 if( World->GetTimerManager().IsTimerActive(_TimerHandle) == true )  
{ 
}

追記

(2018.01.10)

↓のドキュメントではループありのタイマーをClearTimer関数でタイマーのクリアを行っています。
これは実質、タイマーの停止も担っています。
ここで1つ疑問に思ったのが、ループなしのタイマーでは自動的に停止するのでタイマーの停止を目的としたClearTimer関数の使用は必要無くなりますが、クリアを目的としたClearTimerが必要なのかということです。
docs.unrealengine.com

APIにはIsTimerActive関数やTimerExists関数がありますので、こちらを用いてループなしのタイマーが自動停止した後にまだタイマーが存在しているかを調べてみたいと思います。
docs.unrealengine.com

調査

いろいろ調べ方はあると思いますが、簡単な方法で実装します。
bLoopをfalseとしたSetTimer関数をBeginPlayで呼びます。
IsTimerActive関数やTimerExists関数をTickで呼びます。


TimerAct.h

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Engine.h"
#include "TimerAct.generated.h"

UCLASS()
class HOGEPROJECT_API ATimerAct : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ATimerAct();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

protected:
	UWorld* World;
	FTimerHandle _TimerHandle;

protected:
	UFUNCTION()
	void Process();
};

TimerAct.cpp

void ATimerAct::BeginPlay()
{
World=GEngine->GameViewport->GetWorld();
FTimerHandle _TimerHandle;	
World->GetTimerManager().SetTimer(_TimerHandle, this, &ATimerAct::HogeProcess,1.0f, false); //bLoop=false
}

void ATimerAct::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	if (World->GetTimerManager().IsTimerActive(_TimerHandle))
	{
		GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Green, "Active");
	}
	if (World->GetTimerManager().TimerExists(_TimerHandle))
	{
		GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Red, "Exist");
	}
}

void ATimerAct::HogeProcess()
{
}
結果

プレイ開始からHogeProcessが呼ばれるまでタイマーが存在し、その後は自動的にクリアされ、存在しなくなっているようです。


※何か間違えがあればコメントよろしくお願い致します。