高效使用lua作为业务开发语言的秘诀在这里!

导语

你还在使用c++开发UE4吗?会不会感觉太慢了?会不会感觉编译一次就可以去楼下喝杯咖啡了?会不会感觉总是提心吊胆,搞不好什么时候就crash了?现在不用发愁了,slua出unreal版本了,在unity上广泛流行的slua发布了unreal版本,还是那么强大,还是那么好用,你还等什么,赶快上船吧。

1 为何做unreal版本?

目前unreal提供的开发语言包括c++和蓝图,但这2个开发语言都或多或少存在一定的问题,对于c++来说,最大的问题是c++开发人员越来越少,精通c++开发的同学更少,而且c++本身并不是描述业务的最好语言,稍微不留心就容易崩溃或者内存泄露,这是不能接受的,其次unreal下修改c++编译时间太过漫长,如果还修改了header文件,那每次编译真的可以去喝一杯咖啡了,工作效率不高,还有就是调试,如果你想快点运行,选择dev build,则势必丢失一些调试信息,或者出现错误调用栈,或者某些局部变量看不到信息,或者某些断点失效,如果你选择debug build,则启动速度慢,运行慢,好好的一个i7多核计算机,搞的比乌龟都慢,如果正好赶上项目上线,问题频发,想死的心都有。

如果你选择使用蓝图,我只能说作为程序员你骨骼清奇,这玩意都能用于实际业务开发,跑跑demo,做做prototype还行,一般没有业务用蓝图作为主要开发语言用于产品,它最大的问题是不能merge,无法多人协作开发;稍微修改一些接口,某些slot就要重新链接;稍微大一点的蓝图程序看着都头晕。一般蓝图都是作为配置或者流程描述来用。

有介于此,做一套脚本化的开发语言是必须的。

2 Unreal自身提供lua支持?

对,你没有看错,Unreal早期版本其实内建支持lua,只需要自己开启一个宏WITH_LUA,然后重新编译unreal引擎,就可以开启lua,但这个功能在unreal仅仅是概念演示,而且从某个版本之后也不再维护了,实际使用起来也有很多问题,更重要的是,这个功能需要重新编译UE4,这对于大多数拿着引擎就是开箱即用的开发组,重新编译引擎是不现实的,所以我们需要提供一个扩展的插件,不用重新编译,也能方便使用lua来开发。

有介于此,slua 的 unreal 版本诞生了,当然你会问slua什么鬼?嘿嘿嘿,slua就是在unity下广泛流行的lua开发插件,适用于在unity引擎使用lua作为开发语言开发游戏业务,而作者就是我本人,那理所当然,我有必要做一个unreal版本方便slua的用户可以快速迁移到unreal下,因为我是一个负责任的开源软件作者。

3 slua unreal版本提供什么功能?

这说起来就有点激动了,说了这么多也总算进入正题了。

1)对于蓝图类和蓝图方法的调用 什么是蓝图类和蓝图方法呢?就是所以标记了了UCLASS和UFUNCTION的类和函数,UE4为这些类和函数提供反射能力,通过使用反射,slua可以方便调用这些函数,蓝图自己也使用这些反射能力来支持蓝图调用,所以理论上我们使用这些能力来供lua调用,不会比蓝图自己更慢。

2)支持使用lua function作为蓝图的事件代理

在蓝图里支持代理,例如:

这个OnClicked就是代理,可以绑定一个c++函数,或者绑定一个蓝图slot用于触发事件调用函数,slua支持传入一个lua function作为代理函数,调用进入lua函数。例如:

3)对于非蓝图类和非蓝图方法,支持基于静态代码生成的自动导出 和 基于模板展开的手动添加

在实际项目中,我们有很多代码并非是蓝图类,但也需要在lua中使用,比如最常见的FVector,这个类并不是蓝图类(一般蓝图类都是U开头的类),但我们需要在lua中使用FVector来完成位置、方向的计算,我们就需要把FVector导出到lua中使用,为此slua附带了一个工具,通过这个工具可以自动化的导出我们指定的c++类,并生成对应的静态代码,这个工具是基于libclang,它使用libclang产生的反射信息来完成代码生成,这点上类似Unity版的slua,最终生成的代码如下:

可以看到slua将FVector的成员方法都导出了,整体的代码风格与slua unity版本类似。

除了支持静态代码生成的导出,也支持基于可变参数模板的导出,这需要手动添加简单的导出代码,例如:

slua会基于可变参数模板自动展开代码,产生正确参数解析和函数返回值,生成对应的导出函数,不需要对原始c++类做任何注入式的修改。

4)支持数学运算符重载

正如上面提到的FVector,它需要若干计算功能的函数,如果是突兀的Add,Mul看起来很奇怪,而且本身FVector在c++层面也支持运算符重载,所以slua也将这部分能力导出到了lua里,支持在lua层面的运算符重载,方便代码书写。

5)从蓝图直接调用到lua并返回任意返回值

一般使用lua的情景是从c++代码调用lua,但蓝图提供了热更新的能力,有时候我们希望通过蓝图的热更新能力来启动lua代码,这个时候就需要从蓝图调用lua函数,同时返回lua返回值到蓝图,例如有如下lua函数:

我们可以构造如下蓝图来调用lua

我们可以传入任意数量的参数,任意参数类型,并返回任意个数的返回值。

6)支持out类型的蓝图参数和引用类型的c++参数作为返回值

与c#类似,蓝图也支持out类型的参数用于返回多余的返回值,而c++这里,一般我们使用非const引用来返回多余参数(当然也可能不),slua支持这种使用情况,对于out类型的蓝图函数参数会额外返回,对于非const的函数参数也会额外返回,对于c++这里,slua无法区分函数设计时的语义,只要非const的引用类型,都会额外当做返回值返回,当然你可以选择忽略不使用。

7)通过静态代码生成,导出了UE4所有的enum,并使用int支持enum参数

8)支持扩展方法

类似c#的extension method,slua unreal也支持扩展方法,什么是扩展方法呢?比如一个UUserWidget这个蓝图类,存在如下方法:

它并不是蓝图方法,但存在在蓝图类里,我们可能非常需要这个函数能够导出到lua使用,但我们又不想为此修改引擎代码,添加一个UFUNCTION标签,这时我们可以做一个扩展描述:

这样就为UUserWidget添加2个扩展方法,这2个方法可以在lua侧被调用,可以看到第一个GetWidgetFromName方法直接使用UUserWidget的成员方法,第二个RemoveWidgetFromName方法则是手动实现了一个版本,通过这样描述,我们不需要修改UE4引擎就可以为UUserWidget添加扩展的lua方法,非常方便。

最后我们看一个完整使用demo代码:

目前slua unreal持续开发升级中,更多功能不断推出,如果你正在做unreal游戏?如果你正在考虑unreal下如何热更新?如果你正在考虑unreal下的脚本解决方案?不妨试试slua unreal。

4 使用案例

说了这么多,大家一定会问,你吹的那么牛逼,到底有没有项目用?答案是 slua-unreal 已经集成在潘多拉智能营销解决方案,用于支持腾讯多款游戏业务,通过了DAU千万级的产品测试,上线质量稳定,大家可以放心使用。

5 项目地址

slua-unreal已在Github上开源, 开源地址:

https://github.com/Tencent/sluaunreal

大神力作,欢迎Star,Watch,fork,pr!

作者简介

庞巍伟,腾讯移动客户端技术专家、技术总监,slua作者,14年游戏开发经验,对端游、页游、手游都有丰富开发经验,曾参与《梦幻西游》《天下贰》《神将三国》等游戏项目的全程开发工作,目前负责腾讯IEG潘多拉 智能营销解决方案的技术建设、架构工作。

原文发布于微信公众号 - 腾讯开源(tencentopen)

原文发表时间:2018-09-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Danny的专栏

学生信息管理系统验收总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

2483
来自专栏java一日一条

大量参数与信息丢失之间不可不说的故事

代码越少就越好?对象越少就越好?这些都是真的吗?由绝大多数情况来看,这还真的都不一定。

621
来自专栏应用案例

从MapleStory谈游戏状态同步

前言 单机版基本上做了很多功能了,现在开始进入了网络版,最近一直在做一个功能,玩家的状态同步,在做这个功能的时候遇到了一些坑,因此总结记录一下。 背景 在一个网...

3656
来自专栏编程

python笔记5-python2写csv文件中文乱码问题

前言 python2最大的坑在于中文编码问题,遇到中文报错首先加u,再各种encode、decode。 当list、tuple、dict里面有中文时,打印出来的...

3795
来自专栏Java技术栈

Java 9、10、11,哪个才是 Java 程序员的本命?

之前,我们在《Java 10无跳票发布,主推的新特性引争议》的文章中做了一个小的调查,主要是调查现在的Java程序员都在使用哪个版本的Java?根据调查结果,绝...

2213
来自专栏樊华恒的专栏

海量之道系列文章之弱联网优化 (六)

基于一个快速和高效管理的链路之上,做好IO调度和控制,也是提升效能和改善用户体验的重要环节,本节主要来探讨 IO 管理与 强监控。

3750
来自专栏程序猿DD

程序员你为什么这么累【续】:编码习惯之异常处理

导读: 程序员你为什么这么累? 我的编码习惯 - 接口定义 我的编码习惯 - Controller规范 我的编码习惯 - 日志建议 对于大型IT系统,最怕的事情...

36811
来自专栏Kirito的技术分享

设计RPC接口时,你有考虑过这些吗?

RPC 框架的讨论一直是各个技术交流群中的热点话题,阿里的 dubbo,新浪微博的 motan,谷歌的 grpc,以及不久前蚂蚁金服开源的 sofa,都是比较出...

4591
来自专栏CSDN技术头条

【问底】徐汉彬:PHP7和HHVM的性能之争

【导读】徐汉彬曾在阿里巴巴和腾讯从事4年多的技术研发工作,负责过日请求量过亿的Web系统升级与重构,目前在小满科技创业,从事SaaS服务技术建设。最近,PHP7...

2455
来自专栏极客生活

数据分析sql技能之时间处理

其中current_date获取今天的日期,convert_tz函数对某个时间进行时区转换,比如我们直接current_date获得的是北京时间,如果我们需要转...

872

扫码关注云+社区

领取腾讯云代金券