虚幻引擎基础入门(C++) — 【代理说明 09】

前言


代理可以解决一对一或一对多的任务分配工作,还可以解决通知问题
通过代理完成调用某一个对象的一个函数,而不直接持有该对象的任何指针
要调用某个函数,但并不直接去调用,而是通过另一个入口去调用,这就是代理
代理分为:

单播代理(只能进行通知一个人)
多播代理(可以进行多人通知)
动态代理(可以被序列化,体现在可与蓝图进行交互,C++中可以将通知事件进行蓝图广播)

提示:以下是本篇文章正文内容,下面案例可供参考

一、单播代理


单播代理只能绑定一个通知对象,无法进行多个对象通知

通过宏进行构建,分为两种:

        1.有返回类型
        2.没有返回类型

常用绑定函数:

        1.BindUObject:绑定UObject类型对象成员函数的代理
        2.BindSP:绑定基于共享引用的成员函数代理
        3.BindRaw:绑定原始自定义对象成员函数的代理,操作调用需要注意执行需要检查IsBound
        4.BindStatic:绑定全局函数成为代理
        5.UnBind:解除绑定代理关系
        6.绑定中传递的对象类型必须和函数指针所属类的类型相同,否则绑定会报错

调用执行:

        1.执行Execute函数之前,需要检查是否存在有效绑定使用函数 IsBound
        2.Execute 调用代理通知,不安全
        3.ExecuteIfBound 调用代理通知,安全,但是有返回类型的回调函数无法使用此函数执行回调
        4.IsBound 检查当前是否存在有效代理绑定

构建步骤:

        1.通过宏进行声明代理对象类型(根据回调函数选择不同的宏)
        2.使用代理类型进行构建代理对象
        3.绑定回调对象、操作函数
        4.执行代理对象回调

//(在.h文件中)

//1.构建单播代理(此例以无参无返单播代理为例)
//① 单播代理:无参数无返回值单播代理
DECLARE_DELEGATE(CallTest)
//② 1个参数的单播代理
DECLARE_DELEGATE_OneParam(Delegate_OneP, int32)
//③ 2个参数的单播代理
DECLARE_DELEGATE_TwoParams(Delegate_TwoP, int32, int32)
//④ 有返回值,和2个参数的单播代理
DECLARE_DELEGATE_RetVal_TwoParams(float, Delegate_RTwoP, float, float)


UCLASS(config=Game)
class AUECCharacter : public ACharacter
{
    GENERATED_BODY()
public:

    //2. 声明无参无返的单播代理
    CallTest Dnop;

    //3.创建要绑定到无参无返的单播代理上的函数
    void Func();
    virtual void BeginPlay();

};
//(在.cpp文件中)

void AUECCharacter::Func()
{
    UE_LOG(LogTemp, Log, TEXT("---我是无参无返的单播代理!---"));
}



void AUECCharacter::BeginPlay()
{
    Super::BeginPlay();

    //4.将Func函数绑定到单播代理
    Dnop.BindUObject(this, &AUECCharacter::Func);

    //5.判断单播代理是否绑定
    if (Dnop.IsBound())
    {
        //6.调用代理,执行绑定的函数
        Dnop.Execute();
    }
}

二、单播代理

无法构建具有返回值的多播代理,只能构建参数
广播

        调用函数Broadcast,但是调用不保证执行顺序的正确性

构建步骤:

        1.使用宏构建代理类型
        2.使用代理类型构建多播代理对象
        3.添加绑定代理
        4.执行调用

//(在.h文件中)

//1.构建多播代理(不可以构建有返回值的)
//① 无参的多播代理
DECLARE_MULTICAST_DELEGATE(Delegate_MultiNoP)

//② 单播代理:有2个参数的单播代理
DECLARE_MULTICAST_DELEGATE_TwoParams(Delegate_MultiTwoP, int32, int32)


UCLASS(config=Game)
class AUECCharacter : public ACharacter
{
    GENERATED_BODY()
public:

    //2. 声明多播代理
    Delegate_MultiNoP MultiNoP;
    Delegate_MultiTwoP MultiTwoP;

    //3.创建要绑定到无参无返的单播代理上的函数
    void Func1_MultiNoP();
    void Func2_MultiNoP();

    void Func1_MultiTwoP(int32 A, int32 B);
    void Func2_MultiTwoP(int32 C, int32 D);

    virtual void BeginPlay();


};
//(在.cpp文件中)

void AUECCharacter::Func1_MultiNoP()
{
    UE_LOG(LogTemp, Log, TEXT("---------我是无参的多播代理Func1_MultiNoP()!---------"));
}


void AUECCharacter::Func2_MultiNoP()
{
    UE_LOG(LogTemp, Log, TEXT("---------我是无参的多播代理Func2_MultiNoP()!---------"));
}


void AUECCharacter::Func1_MultiTwoP(int32 A, int32 B)
{
    UE_LOG(LogTemp, Log, TEXT("---------我是有2个int参AB的多播代理Func1_MultiTwoP!---------"));
}


void AUECCharacter::Func2_MultiTwoP(int32 C, int32 D)
{
    UE_LOG(LogTemp, Log, TEXT("---------我是有2个int参CD的多播代理Func1_MultiTwoP!---------"));
}

 

void AUECCharacter::BeginPlay()
{
    Super::BeginPlay();

    //4.将多个函数绑定到多播代理
    MultiNoP.AddUObject(this, &AUECCharacter::Func1_MultiNoP);
    MultiNoP.AddUObject(this, &AUECCharacter::Func2_MultiNoP);

    MultiTwoP.AddUObject(this, &AUECCharacter::Func1_MultiTwoP);
    MultiTwoP.AddUObject(this, &AUECCharacter::Func2_MultiTwoP);

    //5.判断多播代理是否绑定
    if (MultiNoP.IsBound())
    {
        //6.调用多播代理,执行绑定的函数
        MultiNoP.Broadcast();
    }

    //5.判断多播代理是否绑定
    if (MultiTwoP.IsBound())
    {
        //6.调用多播代理,执行绑定的函数
        MultiTwoP.Broadcast(2,3);
    }

    //清空所有绑定函数
    MultiNoP.Clear();

    //移除单绑定,需要传递 FDelegateHandle(代理句柄)
    FDelegateHandle DH_Fun = MultiTwoP.AddUObject(this, &AUECCharacter::Func1_MultiTwoP);
    MultiTwoP.Remove(DH_Fun);

    //移除某个对象中的所有函数绑定
    MultiTwoP.RemoveAll(this);


}

三、动态代理


是允许被序列化的数据结构(代理可以被数据化提供给蓝图进行使用),使得可以在.cpp中调用代理广播,并将事件通知到蓝图

UE中的大部分通知事件均使用动态代理,方便蓝图操作(如碰撞通知)

动态代理无法使用带有返回值的函数进行构建

动态代理分为

        动态单播(但是创建动态单播还不如创建普通的多播,单播无法在蓝图中绑定,无法使用宏BlueprintAssignable修饰)
        动态多播

动态代理与上面单播多播的区别:

        动态代理的类型名称需要用 F 开头(动态代理实现了机制构建类)
        动态代理对象类型可以使用UPROPERTY标记;其他代理均无法使用(不加编译可过,调用就会出错)
        动态代理绑定对象的函数需要使用UFUNCTION进行描述(因为需要跟随代理被序列化)

构建步骤

        通过宏进行声明代理对象类型(根据回调函数选择不同的宏)
        使用代理类型进行构建代理对象
        绑定回调对象、操作函数
        执行代理对象回调

总结

        以上就是今天要讲的内容,本文仅仅简单介绍了虚幻引擎中的代理说明使用。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值