依照题目可以知道我们今天要实现的功能是道具的消失与重生。
这里就涉及到道具如何消失,如何重生的问题。
我们规定:
当StartPlayer触碰到道具的时候,道具就消失,间隔5秒钟之后,道具再次在原点重生。
文中的提及的Cube类是AMyActor_Cube类的简称。
文中的提及的Spawn类是AMyActor_Spawn类的简称。
先定义一个ACTOR类的派生类,作为道具,载入任意一个模型即可,这里是载入了Cube模型,并增加了Box类型碰撞体。
以下是Cube类的头文件代码:
请注意第10行,我们宣布了一个代理,这个代理是自己自定义的,也就是说,名字是随便起的。
在32行声明了一个该代理的对象。
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 "MyActor_Cube.generated.h"
8
9
10 DECLARE_DELEGATE(MyDelegateSignature)
11
12 UCLASS()
13 class MYPROJECT5_API AMyActor_Cube : public AActor
14 {
15 GENERATED_BODY()
16
17 public:
18 // Sets default values for this actor's properties
19 AMyActor_Cube();
20
21 protected:
22 // Called when the game starts or when spawned
23 virtual void BeginPlay() override;
24
25 public:
26 // Called every frame
27 virtual void Tick(float DeltaTime) override;
28
29 public:
30 class UStaticMeshComponent* myStaticMesh;
31 class UBoxComponent* box;
32 MyDelegateSignature mySig;
33 virtual void NotifyActorBeginOverlap(AActor* actor)override;
34 FRotator rotate;
35 };
以下是Cube类的源文件代码:
当Cube类的对象被overlap的时候,就会触发代理执行。
1 // Fill out your copyright notice in the Description page of Project Settings.
2
3
4 #include "MyActor_Cube.h"
5 #include "Components\StaticMeshComponent.h"
6 #include "Components\BoxComponent.h"
7 #include "UObject\ConstructorHelpers.h"
8 #include "Engine.h"
9
10
11 // Sets default values
12 AMyActor_Cube::AMyActor_Cube()
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
17 myStaticMesh = CreateDefaultSubobject(TEXT("myStaticMesh"));
18 box = CreateDefaultSubobject(TEXT("box"));
19 box->InitBoxExtent(FVector(80.0f));
20 RootComponent = box;
21 myStaticMesh->SetupAttachment(GetRootComponent());
22
23 auto myStaticMeshAssets = ConstructorHelpers::FObjectFinder(TEXT("StaticMesh'/Engine/BasicShapes/Cube.Cube'"));
24
25 if (myStaticMeshAssets.Succeeded()) {
26 myStaticMesh->SetStaticMesh(myStaticMeshAssets.Object);
27 myStaticMesh->SetWorldScale3D(FVector(0.8f));
28 myStaticMesh->SetSimulatePhysics(false);
29 myStaticMesh->SetEnableGravity(false);
30 }
31
32 rotate = FRotator(0.0f);
33 }
34
35 // Called when the game starts or when spawned
36 void AMyActor_Cube::BeginPlay()
37 {
38 Super::BeginPlay();
39
40 }
41
42 // Called every frame
43 void AMyActor_Cube::Tick(float DeltaTime)
44 {
45 Super::Tick(DeltaTime);
46 myStaticMesh->SetRelativeRotation(FRotator(10.0f*DeltaTime + rotate.Pitch,0.0f,10.0f*DeltaTime + rotate.Roll));
47
48 rotate.Pitch += 0.1f;
49 rotate.Roll += 0.1f;
50 }
51
52 void AMyActor_Cube::NotifyActorBeginOverlap(AActor* actor)
53 {
54 GEngine->AddOnScreenDebugMessage(-1,5,FColor::Blue,TEXT("Touch!"));
55 mySig.ExecuteIfBound();
56 }
那具体执行什么呢?当然是执行消失与重生了。我们再创建一个ACTOR类的派生类Spawn,用于管理Cube类的消失与重生功能。
由于需要定时重生,所以这里肯定会用到FTimerHandle结构体(之前文章都习惯性的说成类,理解意思就好)。
以下是Spawn类的头文件代码:
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 "MyActor_Cube.h"
8 #include "MyActor_Spawn.generated.h"
9
10 UCLASS()
11 class MYPROJECT5_API AMyActor_Spawn : public AActor
12 {
13 GENERATED_BODY()
14
15 public:
16 // Sets default values for this actor's properties
17 AMyActor_Spawn();
18
19 protected:
20 // Called when the game starts or when spawned
21 virtual void BeginPlay() override;
22
23 public:
24 // Called every frame
25 virtual void Tick(float DeltaTime) override;
26
27 public:
28 UPROPERTY()
29 class USceneComponent* scene;
30
31 UFUNCTION()
32 void spawnActor();
33
34 UFUNCTION()
35 void managementActor();
36
37 UPROPERTY()
38 FTimerHandle myTimer;
39
40 UPROPERTY()
41 AMyActor_Cube* myActorCube;
42 };
新定义两个方法,一个方法用于重生Cube,一个方法用于管理Cube。
既然是要和Cube类的对象发生交互,千万不要忘记导入Cube类的头文件。.
以下是Spawn类的源文件代码:
1 // Fill out your copyright notice in the Description page of Project Settings.
2
3
4 #include "MyActor_Spawn.h"
5
6 // Sets default values
7 AMyActor_Spawn::AMyActor_Spawn()
8 {
9 // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
10 PrimaryActorTick.bCanEverTick = true;
11 scene = CreateDefaultSubobject(TEXT("Scene"));
12 RootComponent = scene;
13
14 }
15
16 // Called when the game starts or when spawned
17 void AMyActor_Spawn::BeginPlay()
18 {
19 Super::BeginPlay();
20 spawnActor();
21
22 }
23
24 // Called every frame
25 void AMyActor_Spawn::Tick(float DeltaTime)
26 {
27 Super::Tick(DeltaTime);
28
29 }
30
31 void AMyActor_Spawn::spawnActor()
32 {
33 myActorCube = GetWorld()->SpawnActor(AMyActor_Cube::StaticClass(), GetTransform());
34 myActorCube->mySig.BindUObject(this, &AMyActor_Spawn::managementActor);
35 }
36
37 void AMyActor_Spawn::managementActor()
38 {
39 GetWorld()->GetTimerManager().SetTimer(myTimer, this, &AMyActor_Spawn::spawnActor, 5, false);
40 myActorCube->mySig.Unbind();
41 myActorCube->Destroy();
42 }
先来设计生成Cube类对象的代码,在spawmActor方法中,在世界里产生一个AMyActor_Cube类的实例,并将该实例的代理绑定在Spawn类中的managementActor方法上。
也就是说,当Cube类的对象被Overlap的时候,会开始执行这个被绑定的managementActor方法。
managementActor方法触发后,会每隔5秒钟,调用spawnActor方法,以此往复,这里需要注意的是managementActor里的Timer的LOOP属性设定必须给到false,否则会不断复制,造成管理失控。
因为触碰到Cube类的对象后,该对象会消失,所以Spawn类中的Cube类的指针指向的代理得先解绑,再将对象销毁。
效果图如下:
触碰后物体消失,左上角有提示信息
过5秒钟之后,再次产生一个Cube类的对象。