美文网首页
20 UE5 UOBject的事件和五大委托

20 UE5 UOBject的事件和五大委托

作者: 游戏开发程序员 | 来源:发表于2024-03-28 23:49 被阅读0次

    四类委托

    • 官方步骤: 声明代理、绑定函数到代理、代理调用
      单播委托: 绑定单个可调用对象, 支持返回值.
      多播委托: 可以绑定多个可调用对象, 实质是维持了一个单播委托的数组, 调用时一个个调用.没有返回值.
      事件: 其实就是多播委托, 只是比多播委托多了个friend class OwningType;
      动态委托: 同样分为单播和多播. 只能绑定UFUNCTION, 支持序列化, 可在蓝图中使用(UPROPERTY修饰).
    委托之间的区别和主要方法

    单播委托

    • 只能绑定一个回调函数指针的委托,也只会触发一次。
    • 绑定函数:BindSataic、BindLambda、BindUFunction
    • 执行方面函数:ExecuteIfBound、IsBound、Unbind

    单播委托Demo

    • 1 UObject中的声明委托和定义,以及SelfDelegateCallback
    // 声明两个委托
    DECLARE_DELEGATE(FMyDelegate);
    DECLARE_DELEGATE_OneParam(FMyDelegateWithRetValue, int32);
    
    class UTestObject : public UObject
    {
        GENERATED_BODY()
    
    public:
        FMyDelegate MyDelegate;
    
        FMyDelegateWithRetValue MyDelegateWithRetValue;
    
        void TriggerDelegate();
    
        UFUNCTION()
        // 绑定到自身的委托回调
        void SelfDelegateCallback(int32 var)
        {
            UE_LOG(LogTemp,Warning,TEXT("SelfDelegate Callback :%d"), var);
        }
    
    • 2 绑定lambda函数、UFunction 和 全局函数 触发委托和解绑
            // 构造对象 绑定委托和触发委托
            UTestObject* MyObj = NewObject<UTestObject>();
    
            // BindLambda绑定
            MyObj->MyDelegate.BindLambda([]() {
                // TriggerDelegate 会导致处理委托
                UE_LOG(LogTemp, Warning, TEXT("FMikeTest1::RunTest Delegate triggered!"));
            });
            // 直接执行
            MyObj->MyDelegate.ExecuteIfBound();
    
            // 绑定 到对象成员函数(必须有UFUNCTION()宏)
            MyObj->MyDelegate1P.BindUFunction(MyObj, FName("SelfDelegateCallback"));
            MyObj->MyDelegate1P.ExecuteIfBound(1);
            if(MyObj->MyDelegate1P.IsBound())
            {
                MyObj->MyDelegate1P.Unbind();
            }
    
            // 绑定 全局函数
            MyObj->MyDelegate1P.BindStatic(Delegate1PCallback);
            MyObj->MyDelegate1P.ExecuteIfBound(2);
    
    // 全局函数的委托回调
    void Delegate1PCallback(int32 var)
    {
        UE_LOG(LogTemp,Warning,TEXT("Delegate1PCallback Param :%d"), var);
    }
    

    多播委托

    • 1 声明和定义多播委托
    • 多播委托不能有返回值
    // 多播委托 不可以有返回值,不然用谁的返回值呢?
    DECLARE_MULTICAST_DELEGATE_OneParam(FMyMultDelegate1P, int32);
    
        // 多播(不可以有返回值,不然用谁的返回值呢?)
        FMyMultDelegate1P MyMultDelegate1P;
    
    • 2 添加回调触发函数 全局函数 成员函数 和 Lambda函数
            UTestObject* pUObject = NewObject<UTestObject>();
    
            // 1 BindLambda绑定
            pUObject->MyMultDelegate1P.AddLambda([](int32 n) {
                UE_LOG(LogTemp,Warning,TEXT("From:BindLambda Callback :%d"), n);
            });
    
            // 2 绑定全局函数 第二次移除
            FDelegateHandle Handle = pUObject->MyMultDelegate1P.AddStatic(Delegate1PCallback);
    
            // 3 绑定到对象成员函数(必须有UFUNCTION()宏)
            pUObject->MyMultDelegate1P.AddUFunction(pUObject, FName("SelfDelegateCallback"));
    
    • 3 广播、移除 和 清空
    • FDelegateHandle Handle此句柄用来移除时需要
            // 广播
            if(pUObject->MyMultDelegate1P.IsBound())
            {
                pUObject->MyMultDelegate1P.Broadcast(666);
                // 通过句柄 移除全局函数回调
                pUObject->MyMultDelegate1P.Remove(Handle); 
                pUObject->MyMultDelegate1P.Broadcast(666);
                // 删除pUObject对象上的回调SelfDelegateCallback
                pUObject->MyMultDelegate1P.RemoveAll(pUObject); 
                pUObject->MyMultDelegate1P.Broadcast(666); // 余下Lambda
            }
    

    动态多播委托

    • 动态多播用法类似多播委托
    • 可支持蓝图的回调.
    • AddDynamic绑定的方法得被UFUNCTION标记,否则绑定无效
    • 代理对象用UPROPERTY标记,并设置BlueprintAssignable,暴露给蓝图使用
    // 动态多播:支持在蓝图中使用,类似EventDispatcher
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDynamicMulticastDelegate1P, int32, num);
    
        // 动态多播
    UPROPERTY(BlueprintAssignable) // 添加此标记,蓝图才可用
    FDynamicMulticastDelegate1P MyDynamicDe1P;
    
    
        // 动态多播委托 支持蓝图里回调
        if(1)
        {
            UTestObject* pUObject = NewObject<UTestObject>();
    
            // 只能绑定到对象成员函数(必须有UFUNCTION()宏)
            pUObject->MyDynamicDe1P.AddDynamic(pUObject, &UTestObject::SelfDelegateCallback);
    
            // 广播
            if(pUObject->MyDynamicDe1P.IsBound())
            {
                pUObject->MyDynamicDe1P.Broadcast(1);
                // 解除指定
                pUObject->MyDynamicDe1P.RemoveDynamic(pUObject, &UTestObject::SelfDelegateCallback);
                pUObject->MyDynamicDe1P.Broadcast(2);
                pUObject->MyDynamicDe1P.Clear(); // 全部解绑
                pUObject->MyDynamicDe1P.Broadcast(3);
            }
        }
    
    

    UOBject的事件

    • 底层实现是一个多播委托 Multicast Delegate。
    • 只能够通过声明它的对象来BoardCast、IsBound、Clear
    • 传进来的OwningType其实就是绑定的ClassType,声明为它的友元类,这样一来这个OwningClass就对这个Event的成员有完全Public的访问权限。
    • 通常用法:将Event定义于类内,设为私有,类外通过公开的访问接口进行绑定,触发,解绑,
    • 这种方式起到了保护隐私的作用
        // OwingType:拥有此Event的类,本例中使用本类:UTestObject
        DECLARE_EVENT_OneParam(UTestObject, FMyEvent, int32);
    
        //公开对Event对象的访问接口
        FMyEvent& GetEvent() { return DelegateEvent; }
    
        //将Event设为私有,防止类外直接访问到,起到安全作用
    private:
        FMyEvent DelegateEvent;
    
    • 通过把Evnet绑定在对象上,声明为它的友元类
    • 来达到 只能通过对象来BoardCast、IsBound、Clear的封装性
        // Evnet事件(绑定在某对象上)
        if(1)
        {
            UTestObject* pUObject = NewObject<UTestObject>();
    
            // 1 BindLambda绑定
            pUObject->GetEvent().AddLambda([](int32 n) {
                UE_LOG(LogTemp, Warning, TEXT("From:BindLambda Callback :%d"), n);
                });
    
            // 2 绑定全局函数
            pUObject->GetEvent().AddStatic(Delegate1PCallback);
    
            // 3 绑定到对象成员函数(必须有UFUNCTION()宏)
            pUObject->GetEvent().AddUFunction(pUObject, FName("SelfDelegateCallback"));
    
            // 触发广播
            if (pUObject->GetEvent().IsBound())
            {
                pUObject->GetEvent().Broadcast(666);
                pUObject->GetEvent().Clear(); // 全清
                pUObject->GetEvent().Broadcast(5);
            }
        }
    

    相关文章

      网友评论

          本文标题:20 UE5 UOBject的事件和五大委托

          本文链接:https://www.haomeiwen.com/subject/qdjttjtx.html