« 最近太不小心 | 返回首页 | 让 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 。

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

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

Comments

十年后,前来学习…… 现在GC占引擎40%了……(
我也经历过一个以面向对象的方式来使用lua的项目,客户端服务器都使用lua来做逻辑。但是对象的继承关系没有夸c++与lua的,只是lua本身的继承。个人觉得这种方式用在手游上还是很不错的
我来看一下,是否能 留言成功。
因为看到某些游戏居然用LUA实现了跨平台,对LUA的能力表示非常震惊,最近才开始接触LUA,写惯了C++对这个东西的确非常不适应,而且对于两个语言交换数据也非常不明白,为了追求方便在使用LUAPLUS,最近又想是不是直接用LUABIND,因为感觉很强大,不过在这里看了几篇文章后感觉迷茫了
我觉得一定程度上的对C++的封装有助于程序阅读和扩展。但是不建议完全的封装。
LPC...好怀念啊。。。
拜托。 跟网易说下,把老天下2放出来吧。 那才是精华游戏。 虽然程序上可能有问题,前期把人都卡走光了。。
REGIST_D_CLASS(); REGIST_B_CLASS(); REGIST_D_CLASS_2(); REGIST_UNSAFE_B_CLASS(); REGIST_CLASSMEMBER(); REGIST_CLASSFUNCTION() 这套机制的确不错,不知道dt2这套机制里的汇编代码有没有去掉,要是还没有去掉的话就太迥了... 看了下大唐2的游戏,发现engine下好多bug都没改...
...我是在找lua使用教材进来的,看了评论对我没什么帮助,好象是在选择脚本语言一样,很是迷茫啊. 跟高手对话总是不知所措,大家在讲啥啊?
梦幻的服务器配置是很低的。。。DELL1850
lua讨论群 60028358
呵呵,最近碰到一个项目,连应用UI这一部分,都搞上了厚厚的中间层。好看,是好看
如果是为了增进对 lua 的理解的话,看看 Scheme 就行了,千万别去看 Common Lisp,因为搞不好你就再也不想写 lua 程序了。
刚刚的发现:在此看帖子的时候觉得字体较小,想调大一些,ctrl+鼠标滚轮,结果是整个页面左右移动,而不是缺省的字体放大或缩小…… 我觉得,好处是:可以把页面调到一边,另一边看文档,写程序,打游戏……两不误
在06年方舟内部讲座时我就有说过这个问题,花那么大精力实现一个貌似华丽的接口,隐藏了多少bug啊,完全不知道,最简单,最透明的,才是最好的。。
梦幻单台机器支持一万人同时在线。 是指一个物理进程一万人,还是一个四核(or八核)机器一万人?
看完了,第一感觉是:在Programming in Lua - luachina的中译本译序里,引用的袁承志打五行拳的那一段
呵呵,人各有志!美国有2000多种计算机语言,啥时候中国编程语言有上千种了,信息产业就发达了!引用我的网友的一句话能做编译器什么软件工程也不在话下。我不是说PL0那种教学模型,要是那个也也不说了。lua的实现也没有完全弄明白,lua这种寄存器方式虚拟机java是不屑一顾的,不能承载大型整体代码,优势在于执行代码片断。
我不是做游戏的,我只是一个打酱油的
lua实现的逻辑如果能“更纯”就好了,耗资源的内存操作,数据结构遍历这些都应该不在考虑之内。c++提供良好的接口,lua做逻辑处理。最近研究c++的模板,让面向对象去死吧,呵呵,开玩笑。 “把处理连接的部分独立出来放到单独的进程中”,赞这一点。
大唐2不得不采用原有的C++程序 美术总是牺牲人物的形象来节省资源 新天下与 大唐2或许多多少少有些相同的遭遇
记得以前我翻译过一篇文章叫“Python不是Java” 其实Python的运行效率已经很接近Lua了
@ 夏天, 正如我在 email 里表达过的,设计一门语言,比模仿一门语言实现一次难的多。 实现一个语言,比如一个 lua 编译器,一个 C 编译器,都不是太难的事情。我想任何一个计算机科学的科班生在学校的课程设计里都实现过 pascal 编译器吧? 上学时,我写过一个 C 编译器。05 年的时候也想改进 lua ,实现过一个自认为改良过的语言。 http://blog.codingnow.com/2005/12/compiler.html 但我觉得再做下去(设计一门新语言),尚需要更多的积累。
大话3引擎的效率比不上大话梦幻,也许和多少逻辑在脚本实现也有些关系吧。 更多的使用脚本来写逻辑,牺牲了运行效率,换来了开发效率,也还是个双刃剑啊。
相當有道理。 我很喜歡使用 Lua,不過若是要將 Lua 硬湊成 Object Oriented 的程式語法或者思維概念, 或許反而會失去 Lua 原有的精巧能力與速度特質。 不知道您是否使用過 Squirrel 腳本語言? 它的特點在於語法與 Lua 類似,但對於 OO 有非常好的支援度。
嗯,我蛮赞网易的。
用正确的思想和方法做事,Lua不是C++,老是有人想用C++的风格的面向对象来用Lua. 方法不对啊. http://blog.csdn.net/linkerlin
单服1w - -# 云风同学也喜欢造卫星嘛~~~ 好像还不够1w,咔咔。
“据说最近一年来,他们改进了大话和梦幻的服务器设计,把处理连接的部分独立出来放到单独的进程中 ,使服务器性能大大提高。梦幻西游的服务器,已经可以做到单台机器支持一万人同时在线。” 我对这句很感兴趣,就是不知道网易用的服务器大概是什么配置呢?据我所知,单机支持一万人对于网游来说非常强了...
典型的知道怎么做事(c++用的很熟), 但却不知道该做什么事(在不该使用的时候使用)。
补充一句,如果不完成一个编译器算不上真正的计算机高手!呵呵!开个玩笑,我是武汉理工毕业的。
luabind应该都用不到操作元表!元表是为了能够修改lua的底层操作,面向对象是高阶函数实现的。我曾经打算使用这种方法实现Pyin,太难放弃了,意义不大,纯粹学术游戏,lua的编写者是大学教授玩弄学生的无知!我的看法元表只有学术价值,懂操作元表就能实现编译器了,当然特殊的时候可能会用到!
大系统的基础设施已经有很多现成的,成熟的对象中间件模型是经过千垂百炼的,是众多最佳实践的结晶。 mozilla/xpcom/javascript win32/ole com activex/active script python/c 一般编译部分只用C。C以及C++编写的部分要依赖严格的约定才能粘进系统
WOW告诉我们一个游戏的大部分是解释性的脚本构成的,那些需要效率的C++代码可能还不到10%,WOW的插件几乎都是Lua编写的。
http://rawapyin.blog.sohu.com 看看我正在做的工作,我给你写过邮件,希望改变你的态度,我们到底需要一个什么样的编程语言。 QQ:160404973
云风大大加油
技术的不懂。 玩法是不错了 ,相比大唐1; 至于美术, 我只能说 ,方舟的美术很不错(我觉得是网易最好的美术) ,只是大唐2人物不如大唐1。 飘走~~

Post a comment

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