« 最近太不小心 | 返回首页 | 让 lua 编译时计算 »

Lua 不是 C++

嗯,首先,此贴不是牢骚帖。

话题从最近私人的一点工作开始。应 dingdang 的建议,我最近在帮 大唐无双 做一些程序上的工作。接手做这件事情,是因为这个内部被我们称作 dt2 的游戏 engine 关系重大。公司有至少四个项目在使用(另外三个暂处于研发期,尚未公布)。

dt2 用了大量的 lua 代码构建系统,但从系统设计上,沿袭了老的大唐的许多代码。原来的大唐是用 C++ 构建的,为了利用上这些代码(虽然我觉得这种复用非常无意义,但是其中原因复杂,就不展开谈了),dt2 engine 的开发人员做了一套非常复杂的中间层,把 lua 和 C++ 几乎无缝的联系在了一起。

从表征上看,可以完全不修改 C++ 代码,只额外加上一些东西,便可以在 lua 中得到一个类对象,从语法上相当接近的使用 C++ 的类,并可以对其继承,用 lua 重载其虚函数。甚至可以实现多重继承。

由于项目组隔的比较远,所以直到最近一个月,我才拿到这套东西的文档和源码。我的直觉告诉我,这属于过厚的粘合层,是绝对需要抛弃的。如果不是无双内测初期频频的出现 bug ,可能不会有太多人赞同我这个观点。但事实上,即使这个粘合层实现的绝无问题,完全正确的使用它也几乎是不可能的。这么厚的粘合层很难做到 robust 。

这段时间,在开发维护人员的不懈努力(不包括我,在为这个项目修 bug 的工作上,我只是一打酱油的)下,主要的 bug 也修的差不多了,但是做一些适度的改造也必须开展。跟 engine 的前开发人员聊过,我很能理解这个东西被做成这个样子,以及为什么做这样一个东西的必然性:对 lua 的不熟悉,以及迫切的需要复用 C++ 代码。但是我依然想说,解决问题之道在于,先仔细考虑问题存不存在。不做是最好的做法。

表面上看起来,这个粘合层是设计的是很精妙的,它隐藏了 lua 虚拟机的细节。C++ 程序员在写代码的时候,并不需要实际上也的确是,不知道 lua 的存在。而 lua 程序也不需要关心那个类是用 C++ 实现的。在 lua 中,可以按照 C++ 的对象模型继续对类进行继承扩展。一切都展现的完美无缺。

C++ 的代码从某种程度上也显得非常有水准,template 的灵活使用,可以在可能存在的领域重复利用发挥出功效,大量使用的 stl 容器以及智能指针保证了底层领域的健壮。

如果不是这个粘合层的对象生命期管理出了一点设计上的小问题。在 C++ 的引用计数和 lua 的 gc 管理之间有点搅和不清,我想,这个东西可能就一直用下去了。我也不会被派来对这些代码做 code review 。

没错,代码的 bug 最终都可以改过来,这个设计点上的错误也可以想办法用比较小的代价纠正。但是,仔细的考虑一下,整件事情应该去做吗?在 lua 里实现一个 C++ 的面向对象的对象模型?


面向对象不是 C++ 语言向我们展示的那些东西。这不是 C++ 语言的错,因为 C++ 只是在用它的方式去表达而已。我们可以去寻求 lua 的表达方式,正像 ROR 追寻 ruby 的表达方式一样。

诚然,培养新的语言的程序员,比把一门语言模拟成另一种要困难的多。如果我们用写 C++ 程序的思考方式去写 lua 程序,那么当我们决定把游戏用 lua 重新实现一次。除了性能,我们还会失去很多。

前段时间去广州出差,和西游组的同事吃饭。据说最近一年来,他们改进了大话和梦幻的服务器设计,把处理连接的部分独立出来放到单独的进程中 ,使服务器性能大大提高。梦幻西游的服务器,已经可以做到单台机器支持一万人同时在线。

可惜的是,大话 3 的服务器,依然徘徊在单机三千人左右。表面上最大的区别是,梦幻西游的游戏逻辑是用一种类 C 的脚本语言 LPC 写的,而大话3 则是用的 lua 。

刨除大话 3 更为复杂的逻辑处理的因素,追根到底是,lua 的表达能力更强,导致了程序员用更 C++ 的方式去用 lua 。而原来的 LPC 的代码更接近 C 一些。

不是说 C++ 比 C 慢,对于编译语言来说 C++ 甚至比 C 的执行性能更高。但是对于解释型的动态语言。那种看起来更 C++ 的风格会拖垮运行性能许多。对于开发人员来说 lua 5 以后加入的 meta table 是个好东西,但是任何强大的特性都可能被滥用。有幸 lua 还是门简洁的语言,如果有一天 ruby 在游戏开发圈子里流行起来,我都不敢想会发生怎样的事情 ;)

对于那些新接触 lua 的 C/C++ 程序员来说,我的第一条建议通常是:看看 lisp/scheme 吧,可能 lua 的血统里,scheme 的成分比 C 更多一些。要不玩一下 Haskell ,增进对函数式编程的了解。C++ 借助 template 是可以玩玩函数式编程,但很少有人真的去用。进入 lua 的领域后,你得正正经经的理解一下了。


关于 dt2 engine ,这几天我为之做的最多的事情是重新实现了一个 timer tick 的系统,这个东西很早以前就做过,也有现成的代码。不过 200 行。

但是,重新实现一个的意义在于:把这个子模块剥离出来,绕过原来的厚粘合层。而不是先前的那种设计:在 C++ 里实现一个 CTick 类,然后从 lua 中继承它,再注册回 C++ 中的 CTickMgr 。

可能下一步还会协助开发组的同事把连接管理分离出来,并改进数据库的访问。

最后友情做一个广告:大唐无双 这个游戏还是不错的。美术和玩法方面都有了长足的进步。技术问题我相信在大家的努力下都会慢慢的解决。网易的开发团队还是很强的。

云风 提交于 August 13, 2008 08:13 PM | 固定链接

Comments

十年后,前来学习...... 现在GC占引擎40%了......(

Posted by: farter | (37) June 23, 2018 03:19 PM

我也经历过一个以面向对象的方式来使用lua的项目,客户端服务器都使用lua来做逻辑。但是对象的继承关系没有夸c++与lua的,只是lua本身的继承。个人觉得这种方式用在手游上还是很不错的

Posted by: listener | (36) January 9, 2013 12:44 PM

我来看一下,是否能 留言成功。

Posted by: starshine | (35) February 13, 2012 06:13 PM

因为看到某些游戏居然用LUA实现了跨平台,对LUA的能力表示非常震惊,最近才开始接触LUA,写惯了C++对这个东西的确非常不适应,而且对于两个语言交换数据也非常不明白,为了追求方便在使用LUAPLUS,最近又想是不是直接用LUABIND,因为感觉很强大,不过在这里看了几篇文章后感觉迷茫了

Posted by: FG | (34) January 15, 2012 11:33 PM

我觉得一定程度上的对C++的封装有助于程序阅读和扩展。但是不建议完全的封装。

Posted by: kenlist | (33) December 29, 2010 11:42 AM

LPC...好怀念啊。。。

Posted by: Jacky | (32) October 6, 2010 04:44 AM

拜托。 跟网易说下,把老天下2放出来吧。 那才是精华游戏。 虽然程序上可能有问题,前期把人都卡走光了。。

Posted by: 老天下2 | (31) June 3, 2010 09:27 AM

REGIST_D_CLASS(); REGIST_B_CLASS(); REGIST_D_CLASS_2(); REGIST_UNSAFE_B_CLASS(); REGIST_CLASSMEMBER(); REGIST_CLASSFUNCTION() 这套机制的确不错,不知道dt2这套机制里的汇编代码有没有去掉,要是还没有去掉的话就太迥了... 看了下大唐2的游戏,发现engine下好多bug都没改...

Posted by: graphic | (30) May 7, 2010 09:48 PM

...我是在找lua使用教材进来的,看了评论对我没什么帮助,好象是在选择脚本语言一样,很是迷茫啊. 跟高手对话总是不知所措,大家在讲啥啊?

Posted by: ϧԸ | (29) July 3, 2009 03:45 PM

梦幻的服务器配置是很低的。。。DELL1850

Posted by: zhq7857 | (28) May 4, 2009 08:25 PM

lua讨论群 60028358

Posted by: chinalua | (27) December 1, 2008 02:00 PM

呵呵,最近碰到一个项目,连应用UI这一部分,都搞上了厚厚的中间层。好看,是好看

Posted by: Anonymous | (26) August 16, 2008 08:21 AM

如果是为了增进对 lua 的理解的话,看看 Scheme 就行了,千万别去看 Common Lisp,因为搞不好你就再也不想写 lua 程序了。

Posted by: binghe | (25) August 16, 2008 02:51 AM

刚刚的发现:在此看帖子的时候觉得字体较小,想调大一些,ctrl+鼠标滚轮,结果是整个页面左右移动,而不是缺省的字体放大或缩小...... 我觉得,好处是:可以把页面调到一边,另一边看文档,写程序,打游戏......两不误

Posted by: kingchl | (24) August 15, 2008 08:10 PM

在06年方舟内部讲座时我就有说过这个问题,花那么大精力实现一个貌似华丽的接口,隐藏了多少bug啊,完全不知道,最简单,最透明的,才是最好的。。

Posted by: Anonymous | (23) August 15, 2008 02:21 PM

梦幻单台机器支持一万人同时在线。 是指一个物理进程一万人,还是一个四核(or八核)机器一万人?

Posted by: yezh | (22) August 15, 2008 09:20 AM

看完了,第一感觉是:在Programming in Lua - luachina的中译本译序里,引用的袁承志打五行拳的那一段

Posted by: nothanks | (21) August 15, 2008 08:52 AM

呵呵,人各有志!美国有2000多种计算机语言,啥时候中国编程语言有上千种了,信息产业就发达了!引用我的网友的一句话能做编译器什么软件工程也不在话下。我不是说PL0那种教学模型,要是那个也也不说了。lua的实现也没有完全弄明白,lua这种寄存器方式虚拟机java是不屑一顾的,不能承载大型整体代码,优势在于执行代码片断。

Posted by: 夏天 | (20) August 14, 2008 09:05 PM

我不是做游戏的,我只是一个打酱油的

Posted by: kai | (19) August 14, 2008 08:41 PM

lua实现的逻辑如果能"更纯"就好了,耗资源的内存操作,数据结构遍历这些都应该不在考虑之内。c++提供良好的接口,lua做逻辑处理。最近研究c++的模板,让面向对象去死吧,呵呵,开玩笑。 "把处理连接的部分独立出来放到单独的进程中",赞这一点。

Posted by: dreamsky | (18) August 14, 2008 07:09 PM

大唐2不得不采用原有的C++程序 美术总是牺牲人物的形象来节省资源 新天下与 大唐2或许多多少少有些相同的遭遇

Posted by: shuibian | (17) August 14, 2008 02:43 PM

记得以前我翻译过一篇文章叫"Python不是Java" 其实Python的运行效率已经很接近Lua了

Posted by: ShiningRay | (16) August 14, 2008 12:27 PM

@ 夏天, 正如我在 email 里表达过的,设计一门语言,比模仿一门语言实现一次难的多。 实现一个语言,比如一个 lua 编译器,一个 C 编译器,都不是太难的事情。我想任何一个计算机科学的科班生在学校的课程设计里都实现过 pascal 编译器吧? 上学时,我写过一个 C 编译器。05 年的时候也想改进 lua ,实现过一个自认为改良过的语言。 http://blog.codingnow.com/2005/12/compiler.html 但我觉得再做下去(设计一门新语言),尚需要更多的积累。

Posted by: Cloud | (15) August 14, 2008 12:08 PM

大话3引擎的效率比不上大话梦幻,也许和多少逻辑在脚本实现也有些关系吧。 更多的使用脚本来写逻辑,牺牲了运行效率,换来了开发效率,也还是个双刃剑啊。

Posted by: istone | (14) August 14, 2008 10:31 AM

相當有道理。 我很喜歡使用 Lua,不過若是要將 Lua 硬湊成 Object Oriented 的程式語法或者思維概念, 或許反而會失去 Lua 原有的精巧能力與速度特質。 不知道您是否使用過 Squirrel 腳本語言? 它的特點在於語法與 Lua 類似,但對於 OO 有非常好的支援度。

Posted by: 半路 | (13) August 14, 2008 10:22 AM

嗯,我蛮赞网易的。

Posted by: shellex | (12) August 14, 2008 10:11 AM

用正确的思想和方法做事,Lua不是C++,老是有人想用C++的风格的面向对象来用Lua. 方法不对啊. http://blog.csdn.net/linkerlin

Posted by: Linker Lin | (11) August 14, 2008 10:08 AM

单服1w - -# 云风同学也喜欢造卫星嘛~~~ 好像还不够1w,咔咔。

Posted by: kasicass | (10) August 14, 2008 10:08 AM

"据说最近一年来,他们改进了大话和梦幻的服务器设计,把处理连接的部分独立出来放到单独的进程中 ,使服务器性能大大提高。梦幻西游的服务器,已经可以做到单台机器支持一万人同时在线。" 我对这句很感兴趣,就是不知道网易用的服务器大概是什么配置呢?据我所知,单机支持一万人对于网游来说非常强了...

Posted by: 白菜 | (9) August 14, 2008 09:30 AM

典型的知道怎么做事(c++用的很熟), 但却不知道该做什么事(在不该使用的时候使用)。

Posted by: hacker47@sina.com | (8) August 14, 2008 09:15 AM

补充一句,如果不完成一个编译器算不上真正的计算机高手!呵呵!开个玩笑,我是武汉理工毕业的。

Posted by: 夏天 | (7) August 14, 2008 02:28 AM

luabind应该都用不到操作元表!元表是为了能够修改lua的底层操作,面向对象是高阶函数实现的。我曾经打算使用这种方法实现Pyin,太难放弃了,意义不大,纯粹学术游戏,lua的编写者是大学教授玩弄学生的无知!我的看法元表只有学术价值,懂操作元表就能实现编译器了,当然特殊的时候可能会用到!

Posted by: 夏天 | (6) August 14, 2008 02:01 AM

大系统的基础设施已经有很多现成的,成熟的对象中间件模型是经过千垂百炼的,是众多最佳实践的结晶。 mozilla/xpcom/javascript win32/ole com activex/active script python/c 一般编译部分只用C。C以及C++编写的部分要依赖严格的约定才能粘进系统

Posted by: zzsczz | (5) August 14, 2008 01:21 AM

WOW告诉我们一个游戏的大部分是解释性的脚本构成的,那些需要效率的C++代码可能还不到10%,WOW的插件几乎都是Lua编写的。

Posted by: 夏天 | (4) August 14, 2008 12:41 AM

http://rawapyin.blog.sohu.com 看看我正在做的工作,我给你写过邮件,希望改变你的态度,我们到底需要一个什么样的编程语言。 QQ:160404973

Posted by: 夏天 | (3) August 14, 2008 12:24 AM

云风大大加油

Posted by: sheep | (2) August 13, 2008 10:15 PM

技术的不懂。 玩法是不错了 ,相比大唐1; 至于美术, 我只能说 ,方舟的美术很不错(我觉得是网易最好的美术) ,只是大唐2人物不如大唐1。 飘走〜〜

Posted by: 逗 | (1) August 13, 2008 09:22 PM

Post a comment

非这个主题相关的留言请到:留言本

AltStyle によって変換されたページ (->オリジナル) /