企业网站模板php,苏州建设工程质量监督网站,品牌网站建设熊掌号,网站跳转qq目录
概念
申明动态委托
一、DECLARE_DYNAMIC_DELEGATE
二、DECLARE_DYNAMIC_MULTICAST_DELEGATE
绑定动态委托
一、BindDynamic
二、AddDynamic
三、RemoveDynamic
执行动态委托
一、Execute
二、ExecuteIfBound
三、IsBound
四、Broadcast
动态单播使用示…目录
概念
申明动态委托
一、DECLARE_DYNAMIC_DELEGATE
二、DECLARE_DYNAMIC_MULTICAST_DELEGATE
绑定动态委托
一、BindDynamic
二、AddDynamic
三、RemoveDynamic
执行动态委托
一、Execute
二、ExecuteIfBound
三、IsBound
四、Broadcast
动态单播使用示例
一、两个输入参数无返回值
二、一个输入参数一个返回值
动态多播使用示例 上一篇【UE5 C课程系列笔记】09——多播委托的基本使用-CSDN博客
概念 动态单播/多播委托基于虚幻的反射系统可以在蓝图中进行绑定等操作这使得它在蓝图与 C 交互方面非常有用。动态单播只绑定一个函数而动态多播可以绑定多个函数与非动态的单播/多播相比动态单播/多播提供了蓝图可访问性使其能在蓝图中进行添加绑定、移除绑定以及调用等操作。与动态单播不同的是动态多播委托通常没有返回值。这是因为动态多播委托的主要目的是实现事件广播机制它会依次调用所有绑定的函数。
申明动态委托 一、DECLARE_DYNAMIC_DELEGATE DECLARE_DYNAMIC_DELEGATE 是虚幻引擎中用于声明动态单播委托类型的宏。动态委托允许在运行时更灵活地绑定函数并且支持蓝图UE 的可视化脚本系统与 C 之间的交互。与普通委托相比动态委托提供了一种更动态的方式来处理事件响应和函数回调这在构建复杂的游戏系统尤其是需要在蓝图中方便地配置和处理事件的场景下非常有用。
无参数的动态委托声明DECLARE_DYNAMIC_DELEGATE (FDelegateName)。
带一个参数的动态委托声明DECLARE_DYNAMIC_DELEGATE_OneParam (FDelegateName, ParamType, ParamName)。其中 ParamType 是参数类型ParamName 是参数名称用于在蓝图等环境中更清晰地标识参数。例如声明一个带有一个 int 类型参数的动态委托DECLARE_DYNAMIC_DELEGATE_OneParam (FMyDynamicDelegate, int, MyIntParam)。
二、DECLARE_DYNAMIC_MULTICAST_DELEGATE DECLARE_DYNAMIC_MULTICAST_DELEGATE 用于声明动态多播委托类型的宏。动态多播委托同样支持蓝图和 C 的交互并且可以绑定多个函数。当触发这个委托时所有绑定的函数都会被依次调用这对于实现事件广播机制特别是在需要多个对象或函数对同一事件做出响应且这些响应可能需要在蓝图中灵活配置的场景下非常有用。
无参数的动态多播委托声明DECLARE_DYNAMIC_MULTICAST_DELEGATE (FDelegateName)。
带一个参数的动态多播委托声明DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam (FDelegateName, ParamType, ParamName)。例如声明一个带有一个 float 类型参数的动态多播委托DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam (FMyDynamicMulticastDelegate, float, MyFloatParam)。
绑定动态委托 一、BindDynamic BindDynamic是虚幻引擎UE中用于将函数绑定到动态单播委托上的方法主要用于动态委托。这种绑定方式支持蓝图UE 的可视化脚本系统和 C 之间的交互使得在运行时可以灵活地设置委托所关联的函数并且能够让蓝图方便地对委托事件进行响应。
语法一般为DelegateInstance.BindDynamic(ObjectPtr, FunctionPointer)。其中DelegateInstance是委托实例ObjectPtr是指向包含函数的对象的指针通常是UObject指针FunctionPointer是要绑定的函数的地址。
在如下示例代码中当玩家与一个物体交互时触发一个动态委托。
#include CoreMinimal.h
#include GameFramework/Actor.h
#include MyInteractable.generated.h// 声明一个带有一个FString参数表示交互物体名称的动态委托
DECLARE_DYNAMIC_DELEGATE_OneParam(FOnInteract, FString, InteractableName);UCLASS()
class MYGAME_API AMyInteractable : public AActor
{GENERATED_BODY()
public:// 定义动态委托实例FOnInteract OnInteract;void Interact(FString Name){// 触发动态委托如果已经绑定函数OnInteract.ExecuteIfBound(Name);}
};class UMyInteractUI : public UUserWidget
{
public:void BindToInteractable(AMyInteractable* Interactable){if (Interactable){// 将本对象的函数动态绑定到交互物体的委托上Interactable-OnInteract.BindDynamic(this, UMyInteractUI::OnInteractHandler);}}UFUNCTION(BlueprintImplementableEvent)void OnInteractHandler(FString InteractableName){// 这个函数可以在蓝图中实现具体的UI更新逻辑比如显示交互物体的名称UE_LOG(LogTemp, Warning, TEXT(Interacted with: %s), *InteractableName);}
};
二、AddDynamic AddDynamic主要用于将函数绑定到动态多播委托上。它和BindDynamic类似都是用于动态地将函数关联到委托但AddDynamic更侧重于多播委托的操作用于在已经存在的动态多播委托基础上添加新的函数绑定使得多个函数可以订阅绑定到这个委托当委托被触发调用Broadcast时所有绑定的函数都会被依次调用。
语法为DynamicMulticastDelegateInstance.AddDynamic(ObjectPtr, FunctionPointer)。其中DynamicMulticastDelegateInstance是动态多播委托实例ObjectPtr是指向包含函数的对象的指针通常是UObject指针FunctionPointer是要添加绑定的函数的地址。
在如下示例代码中当角色释放技能时通过动态多播委托通知多个系统进行响应。
#include CoreMinimal.h
#include GameFramework/Actor.h
#include MyCharacter.generated.h// 声明一个带有一个int参数表示技能ID的动态多播委托
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSkillCast, int, SkillID);UCLASS()
class MYGAME_API AMyCharacter : public AActor
{GENERATED_BODY()
public:// 定义动态多播委托实例并使用UPROPERTY(BlueprintAssignable)使其可在蓝图中绑定UPROPERTY(BlueprintAssignable)FOnSkillCast OnSkillCast;void CastSkill(int SkillId){// 触发动态多播委托OnSkillCast.Broadcast(SkillId);}
};class USkillEffectUI : public UUserWidget
{
public:void BindToCharacter(AMyCharacter* Character){if (Character){// 将本对象的函数动态绑定到角色的技能释放委托上Character-OnSkillCast.AddDynamic(this, USkillEffectUI::OnSkillCastHandler);}}UFUNCTION(BlueprintImplementableEvent)void OnSkillCastHandler(int SkillId){// 在这里可以在蓝图中实现显示技能特效等相关逻辑UE_LOG(LogTemp, Warning, TEXT(Skill %d cast. Displaying effect...), SkillId);}
};
三、RemoveDynamic RemoveDynamic用于从动态委托中移除之前通过BindDynamic或AddDynamic绑定的函数。这在对象生命周期结束或者不再需要某个函数对委托事件做出响应时非常重要可以避免委托在触发时调用已不存在或不需要的函数从而防止程序出现错误或意外行为。
语法为DelegateInstance.RemoveDynamic(ObjectPtr, FunctionPointer)。其中DelegateInstance是委托实例ObjectPtr是指向包含函数的对象的指针通常是UObject指针FunctionPointer是要移除绑定的函数的地址。
在如下示例代码中当一个 UI 对象被销毁时需要从任务进度更新委托中移除它绑定的函数
#include CoreMinimal.h
#include UObject/ObjectPtr.h
#include MyQuestSystem.h
#include QuestUI.hvoid UQuestUI::UnbindFromQuestSystem(AMyQuestSystem* QuestSystem)
{if (QuestSystem){// 从任务系统的进度更新委托中移除本对象绑定的函数QuestSystem-OnQuestProgressUpdate.RemoveDynamic(this, UQuestUI::OnQuestProgressUpdateHandler);}
}
执行动态委托 一、Execute 对于动态委托Execute用于触发委托所绑定的函数执行。与普通委托类似它会直接调用绑定的函数。不过在动态委托的语境下它主要用于触发单播动态委托通过DECLARE_DYNAMIC_DELEGATE声明的委托并且要求委托必须已经绑定了函数否则会导致程序崩溃因为它不会检查委托是否绑定函数就尝试调用。 对于无参数的动态委托实例DynamicDelegateInstance使用DynamicDelegateInstance.Execute()。如果动态委托带有参数比如声明了一个带有一个int类型参数的动态委托FMyDynamicDelegate并且已经绑定了函数在执行时语法为DynamicDelegateInstance.Execute(ParamValue)其中ParamValue是符合委托参数要求的int类型的值。
示例代码
#include CoreMinimal.h
#include GameFramework/Actor.h
#include MyInteractableObject.generated.h// 声明一个带有一个FString参数表示交互提示信息的动态委托
DECLARE_DYNAMIC_DELEGATE_OneParam(FOnInteract, FString, InteractionPrompt);UCLASS()
class MYGAME_API AMyInteractableObject : public AActor
{GENERATED_BODY()
public:// 定义动态委托实例FOnInteract OnInteract;void Interact(){FString Prompt Interact with this object;// 假设委托已经绑定了函数直接执行委托OnInteract.Execute(Prompt);}
};class UMyInteractUI : public UUserWidget
{
public:void BindToInteractable(AMyInteractableObject* Interactable){if (Interactable){// 将本对象的函数动态绑定到交互物体的委托上Interactable-OnInteract.BindDynamic(this, UMyInteractUI::OnInteractHandler);}}UFUNCTION(BlueprintImplementableEvent)void OnInteractHandler(FString InteractionPrompt){// 在蓝图中实现显示交互提示信息的逻辑UE_LOG(LogTemp, Warning, TEXT(Interaction prompt: %s), *InteractionPrompt);}
};
二、ExecuteIfBound ExecuteIfBound是一种更安全的执行动态委托的方式主要用于执行单播动态委托。它会先检查动态委托是否已经绑定了函数如果已绑定则执行该函数如果未绑定则不执行任何操作这样可以避免因空指针引用而导致的程序错误。这种方法在不确定委托是否已经绑定函数的情况下非常实用能够增强程序的健壮性。 与Execute类似对于无参数的动态委托实例DynamicDelegateInstance使用DynamicDelegateInstance.ExecuteIfBound()。如果动态委托带有参数例如一个带有一个float类型参数的动态委托语法为DynamicDelegateInstance.ExecuteIfBound(ParamValue)其中ParamValue是符合委托参数要求的float类型的值。
示例代码
#include CoreMinimal.h
#include GameFramework/Actor.h
#include MySkill.generated.h// 声明一个带有一个int参数表示升级后的技能等级的动态委托
DECLARE_DYNAMIC_DELEGATE_OneParam(FOnSkillLevelUp, int, NewLevel);UCLASS()
class MYGAME_API AMySkill : public AActor
{GENERATED_BODY()
public:FOnSkillLevelUp OnSkillLevelUp;void LevelUp(int NewLevel){// 检查委托是否绑定函数如果绑定则执行否则不做任何事OnSkillLevelUp.ExecuteIfBound(NewLevel);}
};
三、IsBound IsBound用于检查动态委托是否已经绑定了函数。它返回一个布尔值true表示动态委托已经绑定了函数false表示没有绑定函数。这个方法在需要根据委托的绑定状态来执行不同逻辑的场景中非常有用比如在触发委托之前先检查是否有函数可供执行或者在动态配置委托绑定关系后检查绑定是否成功等。 对于动态委托实例DynamicDelegateInstance语法为bool IsBound DynamicDelegateInstance.IsBound();
示例代码
#include CoreMinimal.h
#include GameFramework/Actor.h
#include MyEventSystem.generated.h// 声明一个无参数的动态委托
DECLARE_DYNAMIC_DELEGATE(FOnGameEvent);UCLASS()
class MYGAME_API AMyEventSystem : public AActor
{GENERATED_BODY()
public:FOnGameEvent OnGameEvent;void TriggerEventIfBound(){if (OnGameEvent.IsBound()){// 如果委托已经绑定函数则触发委托OnGameEvent.ExecuteIfBound();}else{UE_LOG(LogTemp, Warning, TEXT(Event not bound, no function to execute.));}}
};
四、Broadcast 对于多播动态委托应该使用Broadcast方法来触发委托。Broadcast会按照函数绑定的顺序依次调用所有绑定的函数从而实现事件广播的功能让多个对象或函数对同一个事件做出响应。
示例代码
#include CoreMinimal.h
#include GameFramework/Actor.h
#include MyEventSystem.generated.h// 声明一个带有一个int参数表示事件相关的数值的多播动态委托
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMultiEvent, int, EventValue);UCLASS()
class MYGAME_API AMyEventSystem : public AActor
{GENERATED_BODY()
public:FOnMultiEvent OnMultiEvent;void TriggerEventCorrect(int Value){// 正确的用法使用Broadcast触发多播委托OnMultiEvent.Broadcast(Value);}
};
动态单播使用示例
一、两个输入参数无返回值 在如下代码中定义了一个名为 ADynamicSingleDelegateActor 的类用于处理动态单播委托相关的功能。类中提供了初始化委托、调用委托以及释放委托的函数分别是InitDynamicTwoParamsDelegate、CallDynamicTwoParamsDelegate、ReleaseDynamicTwoParamsDelegate。
头文件
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include CoreMinimal.h
#include GameFramework/Actor.h
#include DynamicSingleDelegateActor.generated.hDECLARE_DYNAMIC_DELEGATE_TwoParams(FDynamicDelegate, FString, InName, int32, InMoney);UCLASS()
class STUDY_API ADynamicSingleDelegateActor : public AActor
{GENERATED_BODY()public: // Sets default values for this actors propertiesADynamicSingleDelegateActor();UFUNCTION(BlueprintCallable)void InitDynamicTwoParamsDelegate(FDynamicDelegate InDelegate);UFUNCTION(BlueprintCallable)void CallDynamicTwoParamsDelegate(FString InStr, int32 InMoney);UFUNCTION(BlueprintCallable)void ReleaseDynamicTwoParamsDelegate();protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public: // Called every framevirtual void Tick(float DeltaTime) override;protected:FDynamicDelegate DynamicTwoParamsDelegate;
};源文件
// Fill out your copyright notice in the Description page of Project Settings.#include Delegate/DynamicSingleDelegateActor.h// Sets default values
ADynamicSingleDelegateActor::ADynamicSingleDelegateActor()
{// Set this actor to call Tick() every frame. You can turn this off to improve performance if you dont need it.PrimaryActorTick.bCanEverTick true;}void ADynamicSingleDelegateActor::InitDynamicTwoParamsDelegate(FDynamicDelegate InDelegate)
{DynamicTwoParamsDelegate InDelegate;
}void ADynamicSingleDelegateActor::CallDynamicTwoParamsDelegate(FString InStr, int32 InMoney)
{DynamicTwoParamsDelegate.ExecuteIfBound(InStr, InMoney);
}void ADynamicSingleDelegateActor::ReleaseDynamicTwoParamsDelegate()
{DynamicTwoParamsDelegate.Clear();
}// Called when the game starts or when spawned
void ADynamicSingleDelegateActor::BeginPlay()
{Super::BeginPlay();}// Called every frame
void ADynamicSingleDelegateActor::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}
编译后在UEEditor中先创建派生自DynamicSingleDelegateActor的蓝图类这里命名为“BP_DynamicSingleDelegateActor” 将“BP_DynamicSingleDelegateActor”拖入视口 在关卡蓝图中设置运行开始时执行InitDynamicTwoParamsDelegate来绑定一个委托事件然后当按下1键时执行委托事件。 执行效果如下当按下1键时成功触发绑定的自定义事件 二、一个输入参数一个返回值 在如下代码中初始化委托、调用委托以及释放委托的函数分别是 InitDynamicTwoParamsOneRetDelegate、CallDynamicTwoParamsOneRetDelegate、ReleaseDynamicTwoParamsOneRetDelegate
头文件
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include CoreMinimal.h
#include GameFramework/Actor.h
#include DynamicSingleDelegateActor.generated.hDECLARE_DYNAMIC_DELEGATE_RetVal_OneParam(int32, FDynamicDelegateRetOne, FString, InName);UCLASS()
class STUDY_API ADynamicSingleDelegateActor : public AActor
{GENERATED_BODY()public: // Sets default values for this actors propertiesADynamicSingleDelegateActor();UFUNCTION(BlueprintCallable)void InitDynamicTwoParamsOneRetDelegate(FDynamicDelegateRetOne InDelegate);UFUNCTION(BlueprintCallable)void CallDynamicTwoParamsOneRetDelegate(FString InStr);UFUNCTION(BlueprintCallable)void ReleaseDynamicTwoParamsOneRetDelegate();protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public: // Called every framevirtual void Tick(float DeltaTime) override;protected:FDynamicDelegateRetOne DynamicOneParamsOneRetDelegate;
};
源文件
// Fill out your copyright notice in the Description page of Project Settings.#include Delegate/DynamicSingleDelegateActor.h// Sets default values
ADynamicSingleDelegateActor::ADynamicSingleDelegateActor()
{// Set this actor to call Tick() every frame. You can turn this off to improve performance if you dont need it.PrimaryActorTick.bCanEverTick false;
}void ADynamicSingleDelegateActor::InitDynamicTwoParamsOneRetDelegate(FDynamicDelegateRetOne InDelegate)
{DynamicOneParamsOneRetDelegate InDelegate;
}void ADynamicSingleDelegateActor::CallDynamicTwoParamsOneRetDelegate(FString InStr)
{int32 returnVal DynamicOneParamsOneRetDelegate.Execute(InStr);UE_LOG(LogTemp, Warning, TEXT(return Value: %d), returnVal);
}void ADynamicSingleDelegateActor::ReleaseDynamicTwoParamsOneRetDelegate()
{DynamicOneParamsOneRetDelegate.Clear();
}// Called when the game starts or when spawned
void ADynamicSingleDelegateActor::BeginPlay()
{Super::BeginPlay();
}// Called every frame
void ADynamicSingleDelegateActor::Tick(float DeltaTime)
{Super::Tick(DeltaTime);
} 编译后在UEEditor中先创建派生自DynamicSingleDelegateActor的蓝图类这里命名为“BP_DynamicSingleDelegateActor” 打开“BP_DynamicSingleDelegateActor”在事件开始后调用InitDynamicTwoParamsOneRetDelegate由于委托有返回值这里用“Create Event”节点 创建一个匹配函数在匹配函数内只打印一下传入的参数并固定返回100 将蓝图“BP_DynamicSingleDelegateActor”拖入视口 在关卡蓝图中通过按键1调用函数CallDynamicTwoParamsOneRetDelegate从而执行委托事件 执行效果如下可以看到成功打印委托的输入输出参数。 动态多播使用示例 在如下代码中定义了一个名为 ADynamicMultiDelegateActor 的类用于处理动态多播委托相关的功能。类中提供了初始化委托、调用委托的函数分别是InitDynamicMultiThree、CallDynamicMultiThree。 动态多播委托 FDynamicMultiThree带有三个不同类型的参数用于传递参数信息。 头文件
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include CoreMinimal.h
#include GameFramework/Actor.h
#include DynamicMultiDelegateActor.generated.hDECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FDynamicMultiThree, FString, InName, int32, InHealth, int32, InMana);UCLASS()
class STUDY_API ADynamicMultiDelegateActor : public AActor
{GENERATED_BODY()public: // Sets default values for this actors propertiesADynamicMultiDelegateActor();void InitDynamicMultiThree(FDynamicMultiThree InDelegate);UFUNCTION(BlueprintCallable)void CallDynamicMultiThree(FString InName, int32 InHealth, int32 InMana);protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public: // Called every framevirtual void Tick(float DeltaTime) override;UPROPERTY(BLUEprintAssignable)FDynamicMultiThree DynamicMultiThree;
};源文件
// Fill out your copyright notice in the Description page of Project Settings.#include DynamicMultiDelegateActor.h// Sets default values
ADynamicMultiDelegateActor::ADynamicMultiDelegateActor()
{// Set this actor to call Tick() every frame. You can turn this off to improve performance if you dont need it.PrimaryActorTick.bCanEverTick false;
}void ADynamicMultiDelegateActor::InitDynamicMultiThree(FDynamicMultiThree InDelegate)
{DynamicMultiThree InDelegate;
}void ADynamicMultiDelegateActor::CallDynamicMultiThree(FString InName, int32 InHealth, int32 InMana)
{DynamicMultiThree.Broadcast(InName, InHealth, InMana);
}// Called when the game starts or when spawned
void ADynamicMultiDelegateActor::BeginPlay()
{Super::BeginPlay();
}// Called every frame
void ADynamicMultiDelegateActor::Tick(float DeltaTime)
{Super::Tick(DeltaTime);
}
创建派生自“DynamicMultiDelegateActor”的蓝图类“BP_DynamicMultiDelegateActor” 打开“BP_DynamicMultiDelegateActor”在事件开始运行时绑定委托事件 在关卡蓝图中再次绑定委托。通过按键1调用CallDynamicMultiThree函数从而调用所有绑定到动态多播委托的函数。 可以看到执行效果如下按一次按键打印了两次“Test”表示两个绑定的委托事件都成功触发。