基于C++代码的UE4学习—— 带一个参数的FParamDelegateSignature动态代理与函数指针

Posted dlak

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于C++代码的UE4学习—— 带一个参数的FParamDelegateSignature动态代理与函数指针相关的知识,希望对你有一定的参考价值。

之前我们使用FStandardDeltegateSignature类进行了无参数的函数绑定,也有人告诉我说叫做观察者模式。

今天我们先使用函数指针完成FStandardDeltegateSignature类的功能。

 

以下是继承自Actor类的PointLightListner类的头文件代码:

 

 1 #pragma once
 2 
 3 #include "CoreMinimal.h"
 4 #include "GameFramework/Actor.h"
 5 #include "ComponentsPointLightComponent.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 "ComponentsBoxComponent.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();

技术图片

 

以上是关于基于C++代码的UE4学习—— 带一个参数的FParamDelegateSignature动态代理与函数指针的主要内容,如果未能解决你的问题,请参考以下文章

UE4 Unlua源码解析8 - Lua与C++之间的参数转换的实现原理

ue4 c++ 模板中的一个小技巧

ue4 c++ 模板中的一个小技巧

UE4 C++ UE4 C++ 入门(无参考项目)——技术宅阿棍儿 学习笔记 更新中~

UE4蓝图与C++交互——射击游戏中多武器系统的实现

最简单的 UE 4 C++ 教程 ——带碰撞和粒子特效的角色操控二十九