委托
委托是一种用于事件处理的机制。使用委托,可以将一个或多个函数绑定到一个事件上,在事件触发时,自动调用这些函数。其作用就是提供一种消息机制,代理调用方法,而不用持有原对象指针。
种类
- 单播委托 : 只能绑定一个函数
- 多播委托 : 可以绑定多个函数,事件触发时,按照绑定顺序执行
- 动态委托 :可以在运行时动态绑定或解绑函数
例子
1. 单播委托带参数
定义单播单参数委托(DECLARE_DELEGATE_OneParam) FCharacterHealthChangedDelegate
Test3Character.h1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
#pragma once
#include "CoreMinimal.h" #include "GameFramework/Character.h" #include "Logging/LogMacros.h" #include "test3Character.generated.h"
class USpringArmComponent; class UCameraComponent; class UInputMappingContext; class UInputAction; struct FInputActionValue;
DECLARE_LOG_CATEGORY_EXTERN(LogTemplateCharacter, Log, All);
DECLARE_DELEGATE_OneParam(FCharacterHealthChangedDelegate, float);
UCLASS(config=Game) class ATest3Character : public ACharacter { GENERATED_BODY() public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true")) float Health;
FCharacterHealthChangedDelegate CharacterHealthChangedDelegate;
public: ATest3Character();
UFUNCTION(BlueprintCallable) void UpdateHealth(const float _Health); };
|
UpdateHealth 方法更新Health值,并触发委托通知
Test3Character.cpp1 2 3 4 5 6 7 8 9 10 11 12 13
| DEFINE_LOG_CATEGORY(LogTemplateCharacter);
void ATest3Character::UpdateHealth(const float _Health) { this->Health = _Health; if (CharacterHealthChangedDelegate.ExecuteIfBound(_Health)) { UE_LOG(LogTemp, Display, TEXT("Character health changed")); } }
|
新建类继承UTextRenderComponent组件
UUHealthTextObserver.h1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| UCLASS(BlueprintType, Blueprintable, meta=(BlueprintSpawnableComponent)) class TEST3_API UUHealthTextObserver : public UTextRenderComponent { GENERATED_BODY() public: FCharacterHealthChangedDelegate CharacterHealthChangedDelegate;
UUHealthTextObserver();
void CharacterHealthChanged(float Health);
UFUNCTION(BlueprintCallable) bool BindHealthChangedDelegate(ATest3Character* ATest3Character); };
|
提供绑定委托方法及处理委托事件方法供调用。
角色health值修改时,触发文本组件更新数字
UUHealthTextObserver.cpp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include "UHealthTextObserver.h"
UUHealthTextObserver::UUHealthTextObserver() { }
void UUHealthTextObserver::CharacterHealthChanged(const float Health) { this->SetText(FText::AsNumber(Health)); }
bool UUHealthTextObserver::BindHealthChangedDelegate(ATest3Character* ATest3Character) { if (ATest3Character == nullptr) return false; if (ATest3Character->CharacterHealthChangedDelegate.IsBound()) return false; ATest3Character->CharacterHealthChangedDelegate.BindUObject(this, &UUHealthTextObserver::CharacterHealthChanged); return true; }
|
在蓝图中新增蓝图类继承C++ Test3Character 角色
新增两个HealthTextRender组件用于调式。

构造函数如下,执行两个组件的绑定方法。

开始事件 以及按下数字1的事件,触发health值变化

运行游戏及按下数字1,仅有一个组件起作用,说明单播委托仅支持单个绑定。


2. 多播委托
ATest3Character.h1
| DECLARE_MULTICAST_DELEGATE_OneParam(FCharacterHealthChangedDelegate, float);
|
ATest3Character.cpp1 2 3 4 5
| void ATest3Character::UpdateHealth(const float _Health) { this->Health = _Health; CharacterHealthChangedDelegate.Broadcast(_Health); }
|
UUHealthTextObserver.cpp1 2 3 4 5 6 7
| bool UUHealthTextObserver::BindHealthChangedDelegate(ATest3Character* ATest3Character) { if (ATest3Character == nullptr) return false; ATest3Character->CharacterHealthChangedDelegate.AddUObject(this, &UUHealthTextObserver::CharacterHealthChanged); return true; }
|
单播改多播委托后,可以看到两个Text组件都能生效了。

3. 动态委托
修改为动态多播委托,注意需要写形参,回调方法需要UFUNCTION修饰,确保蓝图系统能正确运行。
ATest3Character.h1
| DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCharacterHealthChangedDelegate, float, Health);
|
增加移除绑定方法
UUHealthTextObserver.cpp1 2 3 4 5 6 7 8 9 10 11 12 13
| bool UUHealthTextObserver::BindHealthChangedDelegate(ATest3Character* ATest3Character) { if (ATest3Character == nullptr) return false; ATest3Character->CharacterHealthChangedDelegate.AddDynamic(this, &UUHealthTextObserver::CharacterHealthChanged); return true; }
bool UUHealthTextObserver::UnbindHealthChangedDelegate(ATest3Character* ATest3Character) { if (ATest3Character == nullptr) return false; ATest3Character->CharacterHealthChangedDelegate.RemoveDynamic(this, &UUHealthTextObserver::CharacterHealthChanged); return true; }
|
蓝图实现:
- 数字1 更新health
- 数字2 绑定委托
- 数字3 解绑委托
