UE代理

281 阅读3分钟

actor.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
//定义
//单播代理
DECLARE_DELEGATE(FTextDelegateNoparam);  //FTextDelegateNoparam参数是代理的名字
DECLARE_DELEGATE_TwoParams(FTextDelegateTwoparam,float,const FString&);
DECLARE_DELEGATE_RetVal_TwoParams(int32, FTextDelegateTwoparamRetVal, float, const FString&);
//多播代理
//1.多播代理上绑定的函数执行的顺序是不固定的 2.无返回值
DECLARE_MULTICAST_DELEGATE(FMutiDelegateNoparam);
DECLARE_MULTICAST_DELEGATE_TwoParams(FMutiDelegateTwoparam, float, const FString&);
//动态单播代理    
// 1.动态代理可被蓝图调用 2.名称前必须加F
DECLARE_DYNAMIC_DELEGATE_RetVal_OneParam(float, FTestDyDelegateOne, int32, a);
DECLARE_DYNAMIC_DELEGATE(FTestDyDelegate);

//动态多播代理  
//无返回值
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FTestDyMultiDelegate);

UCLASS()
class LX_API AMyActor : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AMyActor();
	UFUNCTION(BlueprintCallable)
	void TestDyDelegate(FTestDyDelegateOne TestDyDelegate);

	UPROPERTY(BlueprintAssignable)
	FTestDyMultiDelegate TestDyMutiDelegate;

	FTestDyDelegateOne TestDyDelegateOne;

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	FTextDelegateTwoparamRetVal TextDelegateTwoparamRetVal;  //声明单播代理
	FTextDelegateNoparam ssss;

	FMutiDelegateTwoparam  MutiDelegateTwoparam;     //声明多播代理


public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UFUNCTION()
	int32 Fun(float a, const FString& s);
	UFUNCTION()
	void FunMuti(float a, const FString& s);
};

actor.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(FTestDyDelegateOne TestDyDelegateO)
{
};

class FtestA
{
public:
	int32 Fun(float a, const FString& s)
	{
		return 5;
	};
	static int32 Fun1(float a, const FString& s)
	{
		return 5;
	};
};


// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
	Super::BeginPlay();

	int32 a;
	int32 b;
	char* p = new char;
	//单播代理
	//TextDelegateTwoparamRetVal.BindUObject(this, &AMyActor::Fun);              //(一)绑定 this代表类名,当前在定义类中使用,用this,,&AMyActor::Fun代表绑定的函数  绑定继承自UObject类的类里面的成员函数
/*	TextDelegateTwoparamRetVal.BindLambda([this](float a, const FString& s)->int32//(二)绑定匿名函数
		{
			return 0;
		});   */
	FtestA C;
	FtestA* D = new FtestA;
	TextDelegateTwoparamRetVal.BindRaw(&C, &FtestA::Fun);                        //(三)绑定原生c++类的方法,如果是指针类型,不用加引用 TextDelegateTwoparamRetVal.BindRaw(D,&FtestA::Fun)
	//TextDelegateTwoparamRetVal.BindSP(A1.ToSharedRef(), &FtestA::Fun);                  //(四)绑定一个共享指针,即纯c++函数,因为纯c++类一般会使用TSharedPtr管理内存
	/*TSharedPtr<FtestA> A1 = MakeShareable(new FtestA);
	TextDelegateTwoparamRetVal.BindStatic(&FtestA::Fun1);          */             //(五)绑定一个静态函数
	/*TSharedPtr<FtestA, ESPMode::ThreadSafe> A1 = MakeShareable(new FtestA);
	TextDelegateTwoparamRetVal.BindSP(A1.ToSharedRef(), &FtestA::Fun);    */      //(六)绑定一个线程安全的共享指针,绑定一个ToSharedRef包裹着的纯c++类
	//TextDelegateTwoparamRetVal.BindUFunction(this, FName("Fun"));          //(六)通过函数名去绑定代理,这里就用到了反射的东西


	if (TextDelegateTwoparamRetVal.IsBound())          //判断是否绑定
		TextDelegateTwoparamRetVal.Execute(23, "qweqwe");  //  ssss.ExecuteIfBound();  //无参的可以将execute与bound绑定在一起
	//TextDelegateTwoparamRetVal.Unbind(); //解除绑定 一般在actor销毁时解除绑定

	//

	//匿名函数
	auto LambdaFun = [a, b](int32, float f) mutable->int32    //[=][a,b]:是以值传递的方式,可以拿到上下文定义的值,  [&]:是以引用传递的方式eg:[&a]  [p]:直接传递指针 [this]:表示可以用类中所有的成员变量,默认不需修改,需加:mutable  如[a,b]() mutable  使用:LambdaFun(23,5.2f)
	{
		b = a;
		return a + b;
	};

	//多播代理
	MutiDelegateTwoparam.AddUObject(this, &AMyActor::FunMuti);   //绑定
	MutiDelegateTwoparam.Broadcast(23, "qweqwe");                //广播

	//对于动态单播代理绑定
	//TestDyDelegateOne.BindUFunction();
	//TestDyDelegateOne.Execute();

	// 对于动态多播代理绑定
	//TestDyMutiDelegate.AddDynamic(this, &AMyActor::FunMuti);   //FunMuti 方法一定要加UFUNCTION    ***********************AddDynamic报错************************
	//TestDyMutiDelegate.Broadcast();




}

// Called every frame
void AMyActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

int32 AMyActor::Fun(float a, const FString& s)
{
	return int32();
}

void AMyActor::FunMuti(float a, const FString& s)
{
}

int32 AAA() {
	return 0;
}

事件

DECLARE_EVENT( OwningType, EventName )

DECLARE_EVENT_OneParam( OwningType, EventName, Param1Type )

DECLARE_EVENT_TwoParams( OwningType, EventName, Param1Type, Param2Type )

DECLARE_EVENT_Params( OwningType, EventName, Param1Type, Param2Type, ... )

将实际的函数绑定到Delegate的方式与Multi-cast Delegate相同

执行Delegate的方式 Broadcast()

举个例子:

    // 第一个参数是实现了事件的类的类名,只有在这个类中才可调用Broadcast()。
// 第二个参数是事件名,它实际上是function signature。
DECLARE_EVENT(AMyTriggerVolume, FPlayerEntered)
 
// 实例化一个事件
FPlayerEntered OnPlayerEntered;
 
// 
UFUNCTION()
void OnTriggerEvent();
 
// 绑定函数到事件
OnPlayerEntered.AddUObject(this, &ATriggerVolEventListener::OnTriggerEvent);
 
// 通过调用 Broadcast()使用此事件
OnPlayerEntered.Broadcast();