UE4多播代理
1.多播委托
1.1 多播介绍
官方多播委托教程:多播委托
官方对于多播委托的描述:可以绑定到多个函数并一次性同时执行它们的委托。
理解:多播委托是也是一种委托类型。一个实例化的多播委托对象可以绑定给多个函数,并且一次性能够同时执行这些函数。
注意
1.多播代理是可以绑定给多个函数的,但是在执行时这些函数的执行顺序是不固定的。
1.2 使用方法
1.2.1 多播宏的声明
与单播使用方法相同,首先进行宏声明
-
相对于单播代理的宏,多播代理的声明宏中多了MULTICAST,其他对于参数个数的描述是相同的,如无参数、一个参数、两个参数等等;
-
多播代理的声明宏中是没有返回值的
//声明无参数的多播代理
DECLARE_MULTICAST_DELEGATE_(FTestMultiDelegateNoparam)
//一个参数的多播代理
DELCARE_MULTICAST_DELEGATE_OneParam(FTestMultiDelegateOneParam, float)
//两个参数的多播代理
DELCARE_MULTICAST_DELEGATE_TwoParams(FTestMultiDelegateTwoParams, float, const FString&)
1.2.2 实例化多播代理对象
FTestMultiDelegateNoparam MultiDelegateNoparam;
FTestMultiDelegateOneParam MultiDelegateOneParam;
FTestMultiDelegateTwoParams MultiDelegateTwoParams;
1.2.3 绑定多播到函数以及执行
绑定
单播代理只绑定到一个函数上,因此在绑定时直接使用Bind**()方法即可。多播委托可以绑定多个函数,当委托出发时,将会调用所有这些函数。因此,多播代理的绑定函数在语义上与数组更加类似。
主要的绑定函数有
//将函数委托添加到该多播委托的调用列表中。
"Add()"
//添加原始C++指针全局函数委托。
"AddStatic()"
//添加原始C++指针委托。原始指针不使用任何类型的引用,因此如果从委托下面删除了对象,则调用此函数可能不安全。调用Execute()时请小心
AddRaw()
//添加基于共享指针的(快速、非线程安全)成员函数委托。共享指针委托保留对对象的弱引用。
"AddSP()"
//添加基于UObject的成员函数委托。UObject委托保留对对象的弱引用。
"AddUObject()"
//从该多播委托的调用列表中删除函数(性能为O(N))。请注意,委托的顺序可能不会被保留!
"Remove()"
//从该多播委托的调用列表中删除绑定到指定UserObject的所有函数。请注意,委托的顺序可能不会被保留!
"RemoveAll()"
还有其他未提及的函数方法等
举例如下
UCLASS()
class HELLOUE4_API AMyActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMyActor();
public:
void FunNoparam();
void FunTwoparamNoRetVal(float a, const FString& s);
int32 FunTwoparamRetVal(float a, const FString& s);
UFUNCTION()
int32 Fun(float a, const FString& s);
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
//在类中定义多播代理对象
FTestMultiDelegateNoparam MultiDelegateNoparam;
FTestMultiDelegateOneParam MultiDelegateOneParam;
FTestMultiDelegateTwoParams MultiDelegateTwoParams;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
执行
多播代理的执行则使用广播,即Broadcast()方法
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyActor.h"
// Sets default values
AMyActor::AMyActor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
void AMyActor::FunNoparam()
{
}
void AMyActor::FunTwoparamNoRetVal(float a, const FString& s)
{
}
int32 AMyActor::FunTwoparamRetVal(float a, const FString& s)
{
return int32(1);
}
// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
Super::BeginPlay();
//绑定
MultiDelegateTwoParams.AddUObject(this, &AMyActor::FunTwoparamNoRetVal);
//执行
MultiDelegateTwoParams.Broadcast(5.2, "Hello Delegate");
}
// Called every frame
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
1.2.4 多播代理的使用时机
适用于同时通知多个函数进行更新的场合
2 动态代理
动态代理和单播代理以及多播代理没什么区别,不同之处在于可以暴露给蓝图使用。就相当于是给蓝图提供了一个可以使用的接口。如果希望在c++中写的代理能够暴露给蓝图使用,就需要使用动态代理。
2.1 动态单播代理
动态单播代理是可以有返回值的,动态代理相对来说较慢,所以只有暴露给蓝图使用时才会使用动态代理。
2.1.1 声明
动态代理在声明时一定要以F开头,并且加分号
.h代码
//无参数无返回值动态单播代理
DELCARE_DYNAMIC_DELEGATE(FTestDynamicDelegate);
//返回值类型为flosat,只有一个参数为Intact2类型的委托对象
//不同的是,动态代理需要暴露给蓝图使用,参数需要提供参数名称,在本例中写为a。
DECLARE_DYNAMIC_DELEGATE_RetVal_OneParam(float, FTestDyDelegateOneParam, int32 , a);
UCLASS()
class HELLOUE4_API AMyActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMyActor();
void FunNoparam();
//把动态代理对象作为函数的参数形式进行绑定
UFUNCTION(BlueprintCallable)
void TestDyDelegate(FTestDynamicDelegate TestDynamicDelegate);
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
.cpp代码
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyActor.h"
// Sets default values
AMyActor::AMyActor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
void AMyActor::TestDyDelegate(FTestDynamicDelegate TestDynamicDelegate)
{
}
void AMyActor::FunNoparam()
{
}
// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
在上述代码中,是直接将动态单播代理对象作为函数的形参使用,然后在蓝图中进行绑定。
//把动态代理对象作为函数的参数形式进行绑定
UFUNCTION(BlueprintCallable)
void TestDyDelegate(FTestDynamicDelegate TestDynamicDelegate);
如果是在c++中绑定,则是和单播代理没什么区别。
先实例化动态单播代理对象,再进行绑定
//无参数无返回值动态单播代理定义
DELCARE_DYNAMIC_DELEGATE(FTestDynamicDelegate);
//实例化对象
FTestDynamicDelegate TestDynamicDelegate;
//绑定
TestDynamicDelegate.BindDynamic(this, AMyActor::FunNoparam);
//执行
TestDynamicDelegate.Execute();
2.2动态多播代理
先在c++中定义委托对象,再在蓝图中定义
//无参数无返回值动态多播代理
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FTestDyMuDelegate);
UPROPERTY(BlueprintAssignable)
FTestDyMuDelegate TestDyMuDelegate;
在c++中绑定
//对于多播代理来说,函数一定要添加UFUNCTION()
UFUNCTION()
void FunNoparam();
//无参数无返回值动态多播代理定义
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FTestDyMuDelegate);
//实例化
FTestDyMuDelegate TestDyMuDelegate;
//绑定
TestDyMuDelegate.AddDynamic(this, AMyActor::FunNoparam);
//执行
TestDyMuDelegate.Broadcast()
浙公网安备 33010602011771号