zoukankan      html  css  js  c++  java
  • 基于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 "ComponentsBoxComponent.h"
      6 #include "UObjectConstructorHelpers.h"
      7 #include "ComponentsStaticMeshComponent.h"
      8 #include "ComponentsSphereComponent.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 }

    最终效果实现如下:

  • 相关阅读:
    使用 Spring data redis 结合 Spring cache 缓存数据配置
    Spring Web Flow 笔记
    Linux 定时实行一次任务命令
    css js 优化工具
    arch Failed to load module "intel"
    go 冒泡排序
    go (break goto continue)
    VirtualBox,Kernel driver not installed (rc=-1908)
    go运算符
    go iota
  • 原文地址:https://www.cnblogs.com/dlak/p/13245984.html
Copyright © 2011-2022 走看看