天天看點

基于C++代碼的UE4學習(四)—— 定時器 

在UE中有專門的類用來完成定時器的功能,它就是FTimerHandle類。

我們來完成一個例子,每隔一段時間之後,讓一個ACTOR自我複制,在一定範圍内随機生成。

這是ACTOR的頭檔案:

1 // Fill out your copyright notice in the Description page of Project Settings.
 2 
 3 #pragma once
 4 
 5 #include "CoreMinimal.h"
 6 #include "GameFramework/Actor.h"
 7 #include "CollisionActor.generated.h"
 8 
 9 UCLASS()
10 class MYPROJECT6_API ACollisionActor : public AActor
11 {
12     GENERATED_BODY()
13     
14 public:    
15     // Sets default values for this actor's properties
16     ACollisionActor();
17 
18 public:
19     UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Properties")
20     class UStaticMeshComponent* myStaticMesh;
21 
22     FORCEINLINE UStaticMeshComponent* GetmyStaticMesh() {
23         return myStaticMesh;
24     }
25 
26 
27     UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Properties")
28     class USphereComponent* myCollision;
29 
30 private:
31     FScriptDelegate startsOverlap;
32     FScriptDelegate endsOverlap;
33 public:
34     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Properties")
35     bool status;
36 public:
37     UFUNCTION(BlueprintCallable,Category = "FUNCTIONS")
38     void onOverlap();
39     UFUNCTION(BlueprintCallable, Category = "FUNCTIONS")
40     void endOverlap();
41 
42 protected:
43     // Called when the game starts or when spawned
44     virtual void BeginPlay() override;
45 
46 public:    
47     // Called every frame
48     virtual void Tick(float DeltaTime) override;
49 
50 
51 public:
52     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Properties")
53     FTimerHandle StarTimer;
54 
55     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Properties")
56     FTimerHandle EndTimer;
57 
58     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Properties")
59     float timeInterval;
60 
61 
62     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Properties")
63     UClass* parentClass;
64 
65     UFUNCTION(BlueprintCallable, Category = "FUNCTIONS")
66     virtual void EndPlay(EEndPlayReason::Type EndReason) override;
67 
68     UFUNCTION(BlueprintCallable, Category = "FUNCTIONS")
69     void spawnSelf();
70 
71     UFUNCTION(BlueprintCallable, Category = "FUNCTIONS")
72     void deletes();
73 };
           

這些代碼是新增在頭檔案中的:

1 public:
 2     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Properties")
 3     FTimerHandle StarTimer;
 4 
 5     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Properties")
 6     FTimerHandle EndTimer;
 7 
 8     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Properties")
 9     float timeInterval;
10 
11 
12     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Properties")
13     UClass* parentClass;
14 
15     UFUNCTION(BlueprintCallable, Category = "FUNCTIONS")
16     virtual void EndPlay(EEndPlayReason::Type EndReason) override;
17 
18     UFUNCTION(BlueprintCallable, Category = "FUNCTIONS")
19     void spawnSelf();
20 
21     UFUNCTION(BlueprintCallable, Category = "FUNCTIONS")
22     void deletes();
23 };
           

擁有兩個處理TImer的對象,一個為start一個為end,他們分别會在BeginPlay和EndPlay兩個繼承自父類并重寫後的函數中實作。spawnSelf函數用來建立自身,deletes函數用來銷毀自身,以免記憶體過載。

以下是ACTOR的源檔案:

1 // Fill out your copyright notice in the Description page of Project Settings.
  2 
  3 
  4 #include "CollisionActor.h"
  5 #include "Components\BoxComponent.h"
  6 #include "UObject\ConstructorHelpers.h"
  7 #include "Components\StaticMeshComponent.h"
  8 #include "Components\SphereComponent.h"
  9 #include "Engine.h"
 10 
 11 // Sets default values
 12 ACollisionActor::ACollisionActor()
 13 {
 14     // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
 15     PrimaryActorTick.bCanEverTick = true;
 16     myStaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("myStaticMesh"));
 17     myCollision = CreateDefaultSubobject<USphereComponent>(TEXT("myCollision"));
 18 
 19     auto myMeshAsset = ConstructorHelpers::FObjectFinder<UStaticMesh>(TEXT("StaticMesh'/Engine/EditorMeshes/ColorCalibrator/SM_ColorCalibrator.SM_ColorCalibrator'"));
 20     auto myMatAsset = ConstructorHelpers::FObjectFinder<UMaterialInterface>(TEXT("Material'/Engine/VREditor/UI/ArrowMaterial.ArrowMaterial'"));
 21 
 22     if (myMeshAsset.Succeeded() && myMatAsset.Succeeded()) {
 23         myStaticMesh->SetStaticMesh(myMeshAsset.Object);
 24         myStaticMesh->SetMaterial(0, myMatAsset.Object);
 25     }
 26     if (!myStaticMesh->IsSimulatingPhysics()) {
 27         myStaticMesh->SetSimulatePhysics(true);
 28         myStaticMesh->SetEnableGravity(false);
 29     }
 30 
 31     RootComponent = myCollision;
 32     myStaticMesh->SetupAttachment(GetRootComponent());
 33     myCollision->InitSphereRadius(120.f);
 34 
 35     startsOverlap.BindUFunction(this, "onOverlap");
 36     myCollision->OnComponentBeginOverlap.Add(startsOverlap);
 37 
 38 
 39     endsOverlap.BindUFunction(this, "endOverlap");
 40     myCollision->OnComponentEndOverlap.Add(endsOverlap);
 41 
 42     status = false;
 43 
 44     parentClass = ACollisionActor::StaticClass();
 45 
 46 
 47     timeInterval = 5.0f;
 48 
 49 }
 50 
 51 void ACollisionActor::onOverlap()
 52 {
 53     GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, TEXT("Touch"));
 54     status = true;
 55     
 56 }
 57 
 58 void ACollisionActor::endOverlap()
 59 {
 60     GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Red, TEXT("OutTouch"));
 61     status = false;
 62 }
 63 
 64 
 65 // Called when the game starts or when spawned
 66 void ACollisionActor::BeginPlay()
 67 {
 68     Super::BeginPlay();
 69 
 70     GetWorld()->GetTimerManager().SetTimer(StarTimer,this,&ACollisionActor::spawnSelf, timeInterval,true);
 71     GetWorld()->GetTimerManager().SetTimer(EndTimer,this,&ACollisionActor::spawnSelf, timeInterval*8,true);
 72 
 73 }
 74 
 75 
 76 
 77 void ACollisionActor::spawnSelf() {
 78     FVector location = FVector(FMath::RandRange(-1000.0f,1000.0f), FMath::RandRange(-1000.0f, 1000.0f), FMath::RandRange(-1000.0f, 1000.0f));
 79     GetWorld()->SpawnActor(parentClass,&location);
 80 }
 81 
 82 void ACollisionActor::EndPlay(EEndPlayReason::Type EndReason)
 83 {
 84     Super::EndPlay(EndReason);
 85     GetWorld()->GetTimerManager().ClearTimer(StarTimer);
 86     GetWorld()->GetTimerManager().ClearTimer(EndTimer);
 87 
 88 }
 89 
 90 
 91 void ACollisionActor::deletes()
 92 {
 93     Destroy();
 94 }
 95 
 96 // Called every frame
 97 void ACollisionActor::Tick(float DeltaTime)
 98 {
 99     Super::Tick(DeltaTime);
100 
101     if (status == true) {
102         myStaticMesh->AddLocalRotation(FRotator(10.0f));
103     }
104     else {
105         myStaticMesh->AddLocalRotation(FRotator(0.0f));
106         myStaticMesh->SetRelativeRotation(FRotator(0.0f));
107     }
108 }
           

想要得到計時器的對象,就得先從世界中獲得時間管理對象:

1 GetWorld()->GetTimerManager().SetTimer(StarTimer,this,&ACollisionActor::spawnSelf, timeInterval,true);
           

通過GetWolrd()獲得世界的指針,再調用GetTimerManager()對象,調用SetTimer函數來設定計時器。

SetTimer常用有四個參數,分别是FTimerHandle類的修,該計時器指向哪個類,該計時器綁定哪個方法,計時器的時間間隔,以及是否循環。

StartTimer這個計時器對象綁定了SpawnSelf方法,通過SpawnActor方法進行自我複制,這裡需要傳入兩個參數,第一個是複制哪個類對象,第二個是在世界裡的位置。

這裡的parentClass指針實際上是指向UClass *parentClass = ACollisionActor::StaticClass();,也就是指向了自己,也就不斷自我複制。

1 void ACollisionActor::spawnSelf() {
2     FVector location = FVector(FMath::RandRange(-1000.0f,1000.0f), FMath::RandRange(-1000.0f, 1000.0f), FMath::RandRange(-1000.0f, 1000.0f));
3     GetWorld()->SpawnActor(parentClass,&location);
4 }
           

結束Play後調用以下方法,實作計時器清零。

EndPlay方法是繼承而來的,還需要寫入參數,意思是給一個結束遊戲的理由,在枚舉型結構體中的EEndplayReason::Type中,EndReason是各種結束理由的形式參數。

找到GetTimerManager之後,通過ClearTimer方法将我們的FTimerHandle類的對象放進去,對其清零。

1 void ACollisionActor::EndPlay(EEndPlayReason::Type EndReason)
2 {
3     Super::EndPlay(EndReason);
4     GetWorld()->GetTimerManager().ClearTimer(StarTimer);
5     GetWorld()->GetTimerManager().ClearTimer(EndTimer);
           

以下方法用于銷毀自身。

1 void ACollisionActor::deletes()
2 {
3     Destroy();
4 }
           

以下方法用于觸發碰撞體之後,進行旋轉。

1 void ACollisionActor::Tick(float DeltaTime)
 2 {
 3     Super::Tick(DeltaTime);
 4 
 5     if (status == true) {
 6         myStaticMesh->AddLocalRotation(FRotator(10.0f));
 7     }
 8     else {
 9         myStaticMesh->AddLocalRotation(FRotator(0.0f));
10         myStaticMesh->SetRelativeRotation(FRotator(0.0f));
11     }
12 }
           

最終效果實作如下:

基于C++代碼的UE4學習(四)—— 定時器