上篇文章写的比较乱,针对上篇文章的问题。我似乎找到答案了。
之前有个概念是我模糊了。
我一直把官方文档中的ReceivedBeginPlay事件认为是C++这边的BeginPlay事件的复写,但其实这是不对的。
我们打开C++这边的Actor类的头文件搜索BeginPlay就能找到如下
C++这边是有ReceivedBeginPlay事件的
细心的朋友会发现这个ReceivedBeginPlay函数是个BlueprintImplementableEvent,这代表
ReceivedBeginPlay在蓝图中实现,C++中调用。调用的地方在BeginPlay实现的倒数第二行。
这表示ReceivedBeginPlay是在BeginPlay后执行的。函数的名字也很直观的说明了这点。
所以上篇文章同时输出lua的ReceivedBeginPlay和C++的BeginPlay就很好解释了。
接着在看另外的问题。既然这是两个完全不同的函数,那我在lua这边覆盖BeginPlay行的通吗?
答案是不行的。
看下LuaActor文件前面的宏就能理解了
Slua这边只是覆写了ue4中的流程事件
如果有lua实现就用lua里的实现,没有的话就用C++里的实现。
而最上面几行则是覆写了C++中的BeginPlay和Tick事件,很明显BeginPlay和Tick事件不在流程事件的范围内,流程事件的参数是要执行的方法名和参数。而方法名是个UFunction类型的指针。Slua是基于UE4的反射系统来实现的,想要让方法实现反射则需要给方法加上UFunction宏。
如知乎上周润发大佬所述:
https://zhuanlan.zhihu.com/p/83605037
没有使用slua时的调用流程如下
使用了slua后的流程如下
LuaActor是slua中的一个重要概念,继承此类的Actor,可以用lua代码来实现其蓝图部分逻辑。通常,我们会将一些调用不频繁,但灵活性较高、改动频繁的逻辑放到蓝图中实现,我们可以把一些方法标记为BlueprintImplementableEvent、BlueprintNativeEvent,在蓝图中实现它们,然后在C++中调用,lua要替代的正是这些方法。
以上引用知乎——南京周润发
上面说到slua 一般用来替换BlueprintImplementableEvent和BlueprintNativeEvent类型的函数。
但我试验后发现其实有用UFunction宏申明的方法都可以。
如下
在lua中调用self:TestFunction的表现是lua方法正常覆盖C++同名方法。
在我感觉告一段落的时候发现这和发哥说的有点不同。
引文中所述:我们可以把一些方法标记为BlueprintImplementableEvent、BlueprintNativeEvent,在蓝图中实现它们,然后在C++中调用,lua要替代的正是这些方法。
但我发现普通UFunction申明的函数也能正常覆盖啊,接着我按官方示例在TestFunction中如下调用C++那边的同名方法时出现问题了。如下:
这样会报错说找不到方法。
接着我分别把此方法设置成BlueprintImplementableEvent、BlueprintNativeEvent类型
发现能正常调用C++(BlueprintNativeEvent),蓝图上(BlueprintImplementableEvent)的方法,没报异常。如下:
结论:lua这边self.Super:xxx 其实就是调C++那边的同名方法。如果lua这边没有覆盖的话,直接self:xxx就能调用C++那边了(使用了元表方法)。
Slua一般是用来覆盖C++那边的BlueprintImplementEvent或是BlueprintNativeEvent方法。
覆盖正常的Blueprintcallable也可以,lua这边用有覆盖方法的时候不能用self.Super:xxx()
Lua这边没有覆盖方法的时候用self:xxx()就能调到C++那边,通样也不能用self.Super:xxx()
BlueprintImplementEvent或是BlueprintNativeEvent则是没有这种限制。