[UE4]中的函数回调实现

UE4中的函数回调(CallBack)

C++中应该有许多种方式的回调,UE C++(UnrealEngine中的C++)则是使用的DELEGATEEVENT来实现。

关于UE C++的代理,存在着以下的几种方式:

  • 静态的Single-cast Delegates
  • Dynamic Single-cast Delegates
  • 静态的Multi-cast Delegates
  • Dynamic Multi-cast Delegates

这几种代理的实现有什么不同需要后续整理,可以参考:

有的时候需要很好的利用一下UE4的官方论坛,像是Stack Overflow一样。

Dynamic Multi-cast Delegates

Dynamic Multi-cast Delegates是唯一的一种可以和UE4的Blueprint联动的代理实现方式。

Dynamic Multi-cast Delegates的UE C++中的声明

 

1
2
3
4
5
6
7
8
9
10
//File: CallbackExample.h
//Class: ACallbackExample

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FZeroInputDelegate);    //没有参数的声明方法
UPROPERTY(BlueprintAssignable, Category="UE C++ Book")    //BlueprintAssignable属性使得这个代理在Blueprint中也取得到。 ->此处在真正的工程中不应该写注释,会出编译问题
FZeroInputDelegate TheZeroInputDelegate;

DECLEAR_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FTwoInputsDelegate, float, FloatVal, int32, IntVal);    //两个参数的声明方法
UPROPERTY(BlueprintAssignable, Category="UE C++ Book")
FTwoInputsDelegate TheTwoInputsDelegate;

 

Tips:

  • 参数最大允许有8个。参数的声明类似上述两个参数的声明,先是类型后是参数名。
  • 参数不同的代理声明只需要将上述的数字换成相应参数的英文就可以,比如说八个参数的情况声明代理的语句就会变成:DELEAR_DYNAMIC_MULTICAST_DELEGATE_EightParams

这样制作的代理,可以在UE的Blueprint中获得到这个代理(似乎是作为Event)并进行实现了。别忘了指定Event与Target。即把这个代理委托给一个类的实例(Instance)。在Blueprint中似乎是以Event而存在的,Blueprint中实现的操作是把这个调用的Event登录到这个代理上去。这样在UE C++中调用这个代理,也会调用Blueprint中的事件,执行这个事件的实现部分。

调用Blueprint中的代理实现

 

1
2
3
4
5
6
7
// File: CallbackExample.cpp
// Class: ACallbackExample

auto ACallbackExample::ExecuteDelegate(const float FloatVal, const int32 IntVal) -> void {
    TheZeroInputDelegate.Broadcast();
    TheTwoInputsDelegate.Broadcast(FloatVal, IntVal);
}

 

官方参考链接:

  • Dynamic Delegates
  • Events

    Blueprint Event与Blueprint Function

    关于事件与函数的区别,没有返回值的被叫做事件,有返回值的叫做函数。是否真实需要验证。在UE C++中可以登录Blueprint的事件,通过给UPROPERTY宏添加属性来完成。话说回来这个是函数,应该使用UFUNCTION宏才对,不知道为什么书上这么说。

用于事件声明的属性有两种,区别的方式是是否在UE C++中有默认的实现。

  • BlueprintImplementableEvent:没有默认实现
  • BlueprintNativeEvent:拥有默认实现

Blueprint Event,Blueprint Function在UE C++中的声明

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// File: CallbackExample.h
// Class: ACallbackExample

// BP Event
UFUNCTION(BlueprintImplementableEvent, Category="UE C++ Book")
void FloatInputEvent(const float FloatVal);

UFUNCTION(BlueprintNativeEvent, Category="UE C++ Book")
void VectorInputEvent(const FVector& VecValue);

// BP Function
UFUNCTION(BlueprintImplementableEvent, Category="UE C++ Book")
float IntInputFunction(const int32 IntInput);

UFUNCTION(BlueprintNativeEvent, Category="UE C++ Book")
TArray<float> VecArrayInputFuncion(const TArray<FVector>& VecValues);

 

Event的默认实现

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// File: CallbackExample.cpp
// Class: ACallbackExample

//static FVector TheVector事先声明的属性

auto ACallbackExample::VectorInputEvent_Implementation(const FVector& VecValue)->void{
    TheVector = VecValue;
}

auto ACallbackExample::VecArrayInputFuncion_Implementation(const TArray<FVector>& VecValues)-> TArray<float>{
    TArray<float> Result;
    for (const auto& Val : VecValue)
        Result.Emplace(FVector::Dist(TheVector, Val));

    return Result;
}

 

以上的代码实装完成之后,继承了上面的CallbackExample类的Blueprint就可以在Blueprint Editor中对上述UE C++中的事件与函数进行重写了。

以上,是对UE中的代理与事件,在可用范围内的总结与实现。但是对于在什么情况下使用这一点上仍然有许多疑问。

为什么要使用Delegate和Event?

关于代理的实现,就算明白了也需要知道需要在什么情况下使用代理,否则没有意义。

关于Event

在UE4中的Blueprint中应没有委托这一说,全部是以Event的名字来称呼的。

Delegate的使用情况

推测1

面向对象的说法只是一种理想的情况,总会有想要实现别人功能的情况。比如说ClassA想要实现一个功能,但是明显这个功能是由ClassB负责的部分,要是自己来实现的话不好,所以自己的话,声明一个Delegate,想用的时候就把这个广播出去(Broadcast),实现了这接口的内容会被调用。

只言片语:

现在我要对一系列数据进行排序,而排序算法可能比较复杂,我不会自己写,我想调用Array.Sort方法,微软为我们提供了快速排序算法。
但是这里有一个问题——我要实现自定义排序规则,比如对于字符串,默认的是按字母顺序,但现在我想这样排序:

按字符串长度排序,只有当长度不同时,再按字母排序。

显然,微软不可能提供这样“个性”的排序方法,那是不是说,就必须让我们自己去写快速排序算法呢?
不需要!
我们只需要使用委托,就能实现这个要求:
string[]strs=”I like C# very much”.Split();
Array.Sort(strs,Rule);
int void Rule(string first,string second)
{
return first.Length==second.Length?first.CompareTo(second):first.Length.CompareTo(second.Length);
}

显然,我并不需要知道快速排序算法的逻辑,我只需要告之排序规则,就实现了我的个性排序。

试问:如果没有委托,你如何解决这个问题?

C++中的代理实现

代理应该涉及了许多知识,完全理解需要后续的更新整理。

参考链接:

 

 

 

 C++调用蓝图

  右键脚本创建,(创建出来的蓝图类右上方有基于哪个C++类作为父类显示)

1、C++类添加

UCLASS(Blueprintable ,ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) //加上Blueprintable才可以创建继续这个类的蓝图类

2、右键创建基于C++脚本的蓝图类

3、(要在场景的物体上或者蓝图类)添加创建的蓝图类为组件,

4、在蓝图左边添加函数TestFunction ,

5、C++类里面写

引入#include "OutPutDeviceDebug.h"

//调用蓝图里的函数   Printf 构建一个FString

FString cmd = FString::Printf(TEXT("TestFunction ABCDEF "));//函数名字 +参数,多个参数要空格

FOutputDeviceDebug device;

//FString类型加个* 转成TChar类型

CallFunctionByNameWithArguments(*cmd,device,NULL,true);

 

 

蓝图调用C++

1、在C++类中声明部分

public:

UFUNCTION(BlueprintCallable, Category = "MyOpenDoor")

void TestFunc(); //蓝图调用的函数

实现部分

  void UTestChair1::TestFunc()

{

UE_LOG(LogTemp, Warning, TEXT("This is a CPP Function"));

}

2、这个类要在蓝图中能添加为组件,所以在类的前面要写

UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )

然后把类添加到蓝图中

3、拖出到事件图表,然后拖出函数调用

如果不做为组件,要把C++ 类拖到场景中,然后在场景蓝图,创建这个类对象的引用,然后调用函数

 

C++事件调用蓝图

1先在头文件上面声明一个代理,名字要以F开头 ,不然编译不通过DECLARE_DYNAMIC_MULTICAST_DELEGATE(FTestRequest);

2声明一个代理变量

public

UPROPERTY(BlueprintAssignable)  //一定要加,不然在蓝图里面找不到

FTestRequest OnTestRequest;

3 在要调用的地方写

  OnTestRequest.Broadcast(); //调用蓝图响应的事件

4把C++ 类添加到蓝图中

5最后要在蓝图类中,选中C++类组件,在事件图表中右键为物体添加事件-在事件调度器 里面选择OnTestRequest ,在拖出Print打印测试

 

C++类声明事件,子类蓝图实现

1 创建一个C++ 类,声明事件


    UFUNCTION(BluePrintImplementableEvent)
    void  DebugTest();

创建基于这个类的蓝图,蓝图右键找到事件DebugTest  进行实现

在C++类里面 调用的地方,写DebugTest();

 

 

C++ 调用蓝图里的函数,蓝图类继承C++ 类

1 在代码声明

//要调用的蓝图里的函数   ,代码不用创建实现
    UFUNCTION(BlueprintNativeEvent,Category=Animation)
    void PlayPopup();

 void Playpop_Implementation(); //一定要定义这个函数,并且实现

2、 在蓝图的Functions,选择overide -PlayPopup

 

会出现要实现的函数

3 在C++类里面 调用的地方,写PlayPopup();

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值