UE4多播代理

1.多播委托

1.1 多播介绍

官方多播委托教程:多播委托
官方对于多播委托的描述:可以绑定到多个函数并一次性同时执行它们的委托。

理解:多播委托是也是一种委托类型。一个实例化的多播委托对象可以绑定给多个函数,并且一次性能够同时执行这些函数。

注意

1.多播代理是可以绑定给多个函数的,但是在执行时这些函数的执行顺序是不固定的。

1.2 使用方法

1.2.1 多播宏的声明

与单播使用方法相同,首先进行宏声明

  1. 相对于单播代理的宏,多播代理的声明宏中多了MULTICAST,其他对于参数个数的描述是相同的,如无参数、一个参数、两个参数等等;

  2. 多播代理的声明宏中是没有返回值的

//声明无参数的多播代理
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()

posted on 2022-03-24 20:11  hxh_space  阅读(857)  评论(0)    收藏  举报

导航