之前我们使用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(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 (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(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(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 alist; 38 39 UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass(), alist); 40 41 for (int i = 0; i < alist.Num(); i++) { 42 APointLightListner * pll= Cast (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 alist; 57 58 UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass(), alist); 59 60 for (int i = 0; i < alist.Num(); i++) { 61 APointLightListner* pll = Cast (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();