1. 创建一个使用定时器的Actor

开启和停止以固定频率运行代码的定时器。

Windows
MacOS
Linux
本页面的内容

若初识 虚幻引擎4 ,建议先阅读编程快速入门 教程。阅读此教程之前应先熟悉创建项目和添加C++代码的操作。

  1. 首先我们将新建一个包含初学者内容包的基础代码项目,命名为HowTo_VTE,然后为其添加一个 Actor 类。在此教程中我们将其命名为Countdown。

    ChooseParentClass.png

    NameYourActor.png

  2. 首先我们将创建一个游戏中可见的简单倒计时定时器。在Countdown.h中将以下代码行添加到类定义的末端:

    int32 CountdownTime;
    
    UTextRenderComponent* CountdownText;
    
    void UpdateTimerDisplay();
  3. 可在Countdown.cpp中创建可渲染文本 Component,并将倒计时时间初始化为3秒。因无需此类 ActorTicking,可将其关闭。ACountdown::ACountdown 应如下所示:

    PrimaryActorTick.bCanEverTick = false;
    
    CountdownText = CreateDefaultSubobject<UTextRenderComponent>(TEXT("CountdownNumber"));
    CountdownText->SetHorizontalAlignment(EHTA_Center);
    CountdownText->SetWorldSize(150.0f);
    RootComponent = CountdownText;
    
    CountdownTime = 3;
  4. ACountdown::UpdateTimerDisplay 应更新文本显示来表明剩余时间,时间到则为零。首次将ACountdown生成到游戏中时将运行此代码。每秒运行一次,直到CountdownTime变量到达零。

    void ACountdown::UpdateTimerDisplay()
    {
        CountdownText->SetText(FString::FromInt(FMath::Max(CountdownTime, 0)));
    }
  5. 指定 定时器 运行函数时将获得一个 定时器柄。需要握住此柄,以便在倒计时结束时将定时器关闭。让我们添加一个函数来进行倒计时,然后将需要控制的定时器柄添加到Countdown.h中的类定义。操作完成后,再添加一个函数,在倒计时结束时执行特殊操作:

    void AdvanceTimer();
    
    void CountdownHasFinished();
    
    FTimerHandle CountdownTimerHandle;

    现在还可在 Countdown.cpp 中编写 ACountdown::AdvanceTimerACountdown::CountdownHasFinished 的主体:

    void ACountdown::AdvanceTimer()
    {
        --CountdownTime;
        UpdateTimerDisplay();
        if (CountdownTime < 1)
        {
            //倒计时结束,停止运行定时器。
            GetWorldTimerManager().ClearTimer(CountdownTimerHandle);
            CountdownHasFinished();
        }
    }
    
    void ACountdown::CountdownHasFinished()
    {
        //改为一个特殊的读出
        CountdownText->SetText(TEXT("GO!"));
    }
  6. 初始化 ACountdown::BeginPlay 中的文字显示——为新的更新函数添加一个调用,并设置一个定时器按每秒一次的频率前进和更新倒计时:

    UpdateTimerDisplay();
    GetWorldTimerManager().SetTimer(CountdownTimerHandle, this, &ACountdown::AdvanceTimer, 1.0f, true);

    我们是在ACountdown::BeginPlay中更新显示,而非ACountdown::ACountdown中。因为在 虚幻编辑器 中设为变量的值将在构造函数之后指定,但在 BeginPlay 之前。将 CountdownTime 公开到编辑器时需要遵守这些值。

  7. 前往 虚幻编辑器 并按下 编译(Compile) 即可检查当前进度。

    CompileFromEditor.png

    然后即可将更新的ACountdown类从 内容浏览器(Content Browser) 放入 关卡编辑器(Level Editor)

    ClassInContentBrowser.png

    LevelEditorText.png

    因倒计时文本是在ACountdown::BeginPlay中设置(而非ACountdown::ACountdown中),默认文本将显示在 关卡编辑器(Level Editor) 中。

    按下 运行(Play) 后,倒计时将按设置进行,显示3、2、1,开始!

此时,我们便成功创建了一个使用定时器的简单类。能够设置倒计时时间,或修改倒计时结束后的行为,这对非编程人员而言可谓受益良多。接下来,我们将把这些特性公开到编辑器。

编写中代码

Countdown.h

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "GameFramework/Actor.h"
#include "Countdown.generated.h"

UCLASS()
class HOWTO_VTE_API ACountdown : public AActor
{
    GENERATED_BODY()

public: 
    // 设置该Actor属性的默认值
    ACountdown();

protected:
    // 游戏开始时或生成时调用
    virtual void BeginPlay() override;

public:
    // 每帧调用
    virtual void Tick( float DeltaSeconds ) override;

    //倒计时运行时长(以秒计)
    int32 CountdownTime;

    UTextRenderComponent* CountdownText;

    void UpdateTimerDisplay();

    void AdvanceTimer();

    void CountdownHasFinished();

    FTimerHandle CountdownTimerHandle;
};

Countdown.cpp

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#include "HowTo_VTE.h"
#include "Countdown.h"

// 设置默认值
ACountdown::ACountdown()
{
    // 设置此Actor每帧调用Tick()。如果不需要,则可将其关闭来改善性能。
    PrimaryActorTick.bCanEverTick = false;

    CountdownText = CreateDefaultSubobject<UTextRenderComponent>(TEXT("CountdownNumber"));
    CountdownText->SetHorizontalAlignment(EHTA_Center);
    CountdownText->SetWorldSize(150.0f);
    RootComponent = CountdownText;

    CountdownTime = 3;
}

// 游戏开始时或生成时调用
void ACountdown::BeginPlay()
{
    Super::BeginPlay();

    UpdateTimerDisplay();
    GetWorldTimerManager().SetTimer(CountdownTimerHandle, this, &ACountdown::AdvanceTimer, 1.0f, true);
}

// 每帧调用
void ACountdown::Tick( float DeltaTime )
{
    Super::Tick( DeltaTime );

}

void ACountdown::UpdateTimerDisplay()
{
    CountdownText->SetText(FString::FromInt(FMath::Max(CountdownTime, 0)));
}

void ACountdown::AdvanceTimer()
{
    --CountdownTime;
    UpdateTimerDisplay();
    if (CountdownTime < 1)
    {
        // 倒计时结束,停止运行定时器。
        GetWorldTimerManager().ClearTimer(CountdownTimerHandle);
        //在定时器结束时按执行所需的特殊操作。
        CountdownHasFinished();
    }
}

void ACountdown::CountdownHasFinished()
{
    //改为一个特殊的读出
    CountdownText->SetText(TEXT("GO!"));
}

欢迎来到全新虚幻引擎4文档站!

我们正在努力开发新功能,包括反馈系统,以便您能对我们的工作作出评价。但它目前还未正式上线。如果您对此页面有任何意见与在使用中遭遇任何问题,请前往文档反馈论坛告知我们。

新系统上线运行后,我们会及时通知您的。

发表反馈意见