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 }

    最终效果实现如下:

  • 相关阅读:
    Java中的Stream流
    JDK1.8之后的新特性和新接口
    IOS6和IOS7的屏幕适配问题
    OC特有语法-分类(category)
    UIApplication的作用
    IO中手机旋转事件的传递
    代码,显示IPhone剩余磁盘空间
    iOS程序的加载过程
    TableView数据源方法的执行顺序
    多线程之线程死锁
  • 原文地址:https://www.cnblogs.com/dlak/p/13245984.html
Copyright © 2011-2022 走看看