之前我们使用FStandardDeltegateSignature类进行了无参数的函数绑定,也有人告诉我说叫做观察者模式。
今天我们先使用函数指针完成FStandardDeltegateSignature类的功能。
以下是继承自Actor类的PointLightListner类的头文件代码:
1 #pragma once
2
3 #include "CoreMinimal.h"
4 #include "GameFramework/Actor.h"
5 #include "Components\PointLightComponent.h"
6 #include "PointLightListner.generated.h"
7
8 UCLASS()
9 class MYPROJECT6_API APointLightListner : public AActor
10 {
11 GENERATED_BODY()
12
13 public:
14 // Sets default values for this actor's properties
15 APointLightListner();
16
17 protected:
18 // Called when the game starts or when spawned
19 virtual void BeginPlay() override;
20
21 virtual void EndPlay(EEndPlayReason::Type EndReason) override;
22
23 public:
24 // Called every frame
25 virtual void Tick(float DeltaTime) override;
26
27
28
29 public:
30
31 UPROPERTY()
32 class UPointLightComponent* pointLight;
33
34 UFUNCTION()
35 void enableLight();
36
37 UFUNCTION()
38 void closeLight();
39
40 UFUNCTION()
41 void SelfLight(FLinearColor color);
42 };
以下是继承自Actor类的PointLightListner类的源文件代码:
其中注释起来的代码是之前用作FStandardDelegateSignature类内容设计的,这里可以暂时忽略。
1 // Fill out your copyright notice in the Description page of Project Settings.
2
3
4 #include "PointLightListner.h"
5 #include "Kismet/GameplayStatics.h"
6 #include "MyProject6GameModeBase.h"
7
8 // Sets default values
9 APointLightListner::APointLightListner()
10 {
11 // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
12 PrimaryActorTick.bCanEverTick = true;
13 pointLight = CreateDefaultSubobject<UPointLightComponent>(TEXT("pointLight"));
14 pointLight->SetVisibility(true);
15 pointLight->SetLightColor(FLinearColor::Blue);
16 }
17
18 // Called when the game starts or when spawned
19 void APointLightListner::BeginPlay()
20 {
21 Super::BeginPlay();
22 /*
23 auto ParentGameMode = UGameplayStatics::GetGameMode(GetWorld());
24
25 AMyProject6GameModeBase* myGameModeBase = Cast<AMyProject6GameModeBase>(ParentGameMode);
26
27 if (myGameModeBase) {
28 //myGameModeBase->myDelegate1.BindUObject(this,&APointLightListner::enableLight);
29 myGameModeBase->myDelegate2.BindUObject(this, &APointLightListner::closeLight);
30 myGameModeBase->myOneParamDelegate.BindUObject(this, &APointLightListner::SelfLight);
31 }
32 */
33
34 }
35
36 void APointLightListner::EndPlay(EEndPlayReason::Type EndReason)
37 {
38
39 Super::EndPlay(EndReason);
40 /*
41 auto ParentGameMode = UGameplayStatics::GetGameMode(GetWorld());
42
43 AMyProject6GameModeBase* myGameModeBase = Cast<AMyProject6GameModeBase>(ParentGameMode);
44
45 if (myGameModeBase) {
46 //myGameModeBase->myDelegate1.Unbind();
47 myGameModeBase->myDelegate2.Unbind();
48 myGameModeBase->myOneParamDelegate.Unbind();
49 }
50 */
51
52 }
53
54 // Called every frame
55 void APointLightListner::Tick(float DeltaTime)
56 {
57 Super::Tick(DeltaTime);
58
59 }
60
61
62 void APointLightListner::enableLight() {
63 pointLight->SetLightColor(FLinearColor::Red);
64 }
65
66
67 void APointLightListner::closeLight() {
68 pointLight->SetLightColor(FLinearColor::Blue);
69 }
70
71 void APointLightListner::SelfLight(FLinearColor color)
72 {
73 pointLight->SetLightColor(color);
74 }
实现方是一个灯组件及其开关的方法及颜色。现在要实现触发方。
以下是继承自Actor类的TriggerS类的头文件代码:
它导入了PointLightListner类的头文件,因为要访问它类中的方法。
再建立一个Box的碰撞体。
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 "PointLightListner.h"
8 #include "Components\BoxComponent.h"
9 #include "TriggerS.generated.h"
10
11
12 UCLASS()
13 class MYPROJECT6_API ATriggerS : public AActor
14 {
15 GENERATED_BODY()
16
17 public:
18 // Sets default values for this actor's properties
19 ATriggerS();
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 UFUNCTION(BlueprintCallable)
31 virtual void NotifyActorBeginOverlap(AActor* actor) override;
32
33 UFUNCTION(BlueprintCallable)
34 virtual void NotifyActorEndOverlap(AActor* actor) override;
35 UPROPERTY()
36 class UBoxComponent* box;
37
38 };
1 // Fill out your copyright notice in the Description page of Project Settings.
2
3
4 #include "TriggerS.h"
5 #include "Kismet/GameplayStatics.h"
6
7 // Sets default values
8 ATriggerS::ATriggerS()
9 {
10 // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
11 PrimaryActorTick.bCanEverTick = true;
12 box = CreateDefaultSubobject<UBoxComponent>(TEXT("box"));
13 RootComponent = box;
14 box->InitBoxExtent(FVector(80.0f));
15 }
16
17 // Called when the game starts or when spawned
18 void ATriggerS::BeginPlay()
19 {
20 Super::BeginPlay();
21
22 }
23
24 // Called every frame
25 void ATriggerS::Tick(float DeltaTime)
26 {
27 Super::Tick(DeltaTime);
28
29 }
30
31 void ATriggerS::NotifyActorBeginOverlap(AActor* actor)
32 {
33 void (APointLightListner:: * PL)();
34 PL = &APointLightListner::enableLight;
35
36
37 TArray<AActor*> alist;
38
39 UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass(), alist);
40
41 for (int i = 0; i < alist.Num(); i++) {
42 APointLightListner * pll= Cast<APointLightListner>(alist[i]);
43 if (pll) {
44 (pll->*PL)();
45 }
46 }
47 }
48
49 void ATriggerS::NotifyActorEndOverlap(AActor* actor)
50 {
51
52 void (APointLightListner:: * PL)();
53 PL = &APointLightListner::closeLight;
54
55
56 TArray<AActor*> alist;
57
58 UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass(), alist);
59
60 for (int i = 0; i < alist.Num(); i++) {
61 APointLightListner* pll = Cast<APointLightListner>(alist[i]);
62 if (pll) {
63 (pll->*PL)();
64 }
65 }
66 }
在NotifyActorBeginOverlap和NotifyActorEndOverlap方法中建立数组和PointLightListner类的函数指针,指向类中的方法。
效果如下,可以达到同样效果。
接下来看带有一个参数的FParamDelegateSignature类代理,其使用方法与FStandardDelegateSignature类几乎完全一样,除了两个地方,在声明阶段是这样的。
1 DECLARE_DELEGATE_OneParam(FParamDelegateSignature,FLinearColor)
声明带参数的代理,用DECLARE_DELEGATE_OneParam()宏定义,我试了下,可以一直写到DECLARE_DELEGATE_NineParam(),意思就是可以绑定带有9个参数的方法。
宏定义的第一个参数中传入代理类型,这里就是FParamDelegateSignature类,第二个参数是要绑定的方法需要传入的数据类型,这里需要传入的是一个FLinearColor类型。
第二个地方不同的是,在FStandardDelegateSignature类对象将类中的绑定好的方法进行执行的时候,用到的是ExcuteIfBound方法,而FParamDelegateSignature类对象执行绑定好的方法的时候,使用的是Excute方法。
FParamDelegateSignature类其他例如绑定方法,解绑方法,与FStandardDelegateSignature类都是相同的。
BindUObject()
Unbind();