学习虚幻C++开发日志——定时器
官方文档:虚幻引擎中的Gameplay定时器 | 虚幻引擎 5.5 文档 | Epic Developer Community | Epic Developer Community
定时器
安排在经过一定延迟或一段时间结束后要执行的操作。例如,您可能希望玩家在获取某个能力提升道具后变得无懈可击,然后10秒钟后恢复可受伤害状态。又或者,您可能希望玩家在穿过一间充满毒气的房间时,每秒受到一次伤害。这些操作都可以使用定时器来实现。
注意:定时器消耗比较大,可用虚幻自带的GAS框架进行大消耗的更新等操作。
基础写法
先创建一个继承于Actor的类命名为TimerActor。
在头文件添加代码:
public:
//此函数具有重复调用作用
void RepeatingFunction();
protected:
//定义一个定时器
FTimerHandle MyTimerHandle;
//定时3秒
int32 RepeatingCallsRemaining = 3;
在源文件添加代码:
void ATimerActor::BeginPlay()
{
Super::BeginPlay();
//拿到时间管理器
FTimerManager& ThisTimerManager = GetWorldTimerManager();
ThisTimerManager.SetTimer(MyTimerHandle, this, &ATimerActor::RepeatingFunction, 1.0f, true, 2.0f);
}
void ATimerActor::RepeatingFunction()
{
// 调用该函数达到足够次数后,清空定时器。
if (--RepeatingCallsRemaining <= 0)//此写法为先减在判断
{
GetWorldTimerManager().ClearTimer(MyTimerHandle);
//在输出日志去查看效果
UE_LOG(LogTemp, Warning, TEXT("Timer End!"));
}
// 在此进行一些操作...
}
在Output Log中经过3秒显示自定义日志。
引擎源码片段:
SetTimer()
ClearTimer()
进阶写法
先创建一个继承于Actor的类命名为TimerActor。
在头文件添加代码:
public:
//渲染组件,将定时器显示在场景中
class UTextRenderComponent* CountdownText;
protected:
void AdvanceTimer();
void UpdataTimerDisplay();
//此宏可将其在蓝图进行调用
UFUNCTION(BlueprintNativeEvent)
void CountdownHasFinshed();
protected:
//可在编辑器进行修改
UPROPERTY(EditAnywhere)
int32 CountdownTime;
FTimerHandle CountdownTimerHandle;
在基于此类创建的蓝图子类中:
在源文件添加代码:
//先添加头文件,以调用组件
#include"Components/TextRenderComponent.h"
先在默认构造函数中进行初始定义:
ALearnCountDownActor::ALearnCountDownActor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = false;
CountdownText = CreateDefaultSubobject<UTextRenderComponent>(TEXT("CountdownNumber"));//可在蓝图组件处查看到名称
CountdownText->SetHorizontalAlignment(EHTA_Center);//设置水平对齐
CountdownText->SetWorldSize(150.0f);
RootComponent = CountdownText;
CountdownTime = 3;
}
void ALearnCountDownActor::UpdataTimerDisplay()
{
CountdownText->SetText(FText::FromString(FString::FromInt(FMath::Max(CountdownTime,0))));//此处类型转换
}
//_Implementation表明原生实现
void ALearnCountDownActor::CountdownHasFinshed_Implementation()
{
//改为特殊读出
CountdownText->SetText(FText::FromString(TEXT("Finsh!")));
}
void ALearnCountDownActor::AdvanceTimer()
{
--CountdownTime;
//此处类似递归
UpdataTimerDisplay();
if (CountdownTime < 1)
{
//倒数完成,停止运行定时器
GetWorldTimerManager().ClearTimer(CountdownTimerHandle);
CountdownHasFinshed();//出口
}
}
void ALearnCountDownActor::BeginPlay()
{
Super::BeginPlay();
//先更新
UpdataTimerDisplay();
GetWorldTimerManager().SetTimer(CountdownTimerHandle, this, &ALearnCountDownActor::AdvanceTimer, 1.0f, true);
}
思路: 先进行初始化,用FMath::Max取最大值返回数值从而更新,在AdvanceTimer函数中运用类似递归思想进行循环并结束,上述做法单独为一个函数,将其返回的参数在BeginPlay()中用GetWorldTimerManager().SetTimer进行处理。