本年度的工作包括了M项目和RTS项目开发,简单概括一下。
M项目方面依然占据最大的开发工期,包括制作、维护,优化还有客户端方面的工作。
RTS方面,大概在8月中开始过渡到这边的工作,分立项前和立项后两个阶段。
立项前主要是纯客户端的工作,包括相关工具的学习(客户端引擎、cocosui编辑器)。由于客户端的经验比较少,尤其是3D游戏,所以主要帮忙做一些UI或者逻辑的修改。这样能保证产出,让客户端核心可以专心做更重要的工作。
立项后主要是服务端方面的前期工作
由于这套服务端框架是第一次接触,没有经验,没有文档,所以很多工作其实都是摸索中进行,经常需要写demo去验证想法。 另外新引擎其实也是有很多坑的,它有比旧引擎好的地方,但并不是所有东西都是想象中的那么美好。 搞这些底层相关工作本身也比较花时间,因为途中会遇到各种意想不到的坑,产出没法得到很好的保证。 这个过程踩过的坑,解决了的问题,我会把经验积累下来,希望能为后面的人提高产出。 目前最主要的事情是调通了客户端到服务端,及服务端到数据库的通信框架,下一步是把战斗做成联网的。
按我初步的设想,这个战斗是直接做到引擎的游戏进程里面,因为这样足够简单,可以快速的实现。 但这样是有一个问题的,就是战斗协议,都经过了网关的分发,这里可能会产生性能问题。 后面估计还是需要写一个独立的战斗服进程,每个进程可以跑多个战斗,进程数大致等于CPU核数,协议可以换成包体更优秀的UDP,序列化和反序列化换成C++来实现等,这样最终应该是比较靠谱的方案。 等战斗迁移完成,看到联机效果了,我会着手开始实现战斗服进程这一块功能。不管怎样,work first optimize later,先做出来再说,优化的方法总是有的。
关于产品、代码质量、服务端技术的一些思考。
·产品
RTS这种游戏,我觉得在移动设备上是挺难做的,主要是客观因素的制约。
从技术上来说,游戏类型复杂,非常重度,实现起来难度高;实时PVP,需要解决网络同步问题,移动设备网络对这方面要求更高; 战斗单位多,意味着更多的单位计算、AI和渲染,还有更多的状态同步;整个团队其实没怎么做过这种RTS类的游戏,很多技术、工具需要摸索,也一定会遇到很多技术上的问题,需要攻克。
从设计上来说,存在各种设计和硬件的矛盾冲突。比如手机屏幕小,而游戏需要显示很多单位; 触摸屏设备交互方式有限,而游戏需要非常复杂的操作等等。这些问题,如果不做好取舍,很容易陷入设计的死胡同。 比如之前”双指拖屏“的问题,如果demo的时候侥幸过了,后面功能做下去,只要设备支持,肯定会出现”三指拖屏“甚至”四指拖屏”。 又比如之前曾经提到过的,做点击和拖动两套兼容的交互方案,可以让玩家自由去选择,或者新手阶段先教点击,后面玩家留下来了,强行转拖动。 做这个兼容,显然不如把其中一种操作做到极致,让产品能提早上线,来得更重要,更不说后面的维护成本。
堆叠功能其实并不难,难的是站在一个全局的角度去做权衡,做取舍。 哪些功能在现有的条件下,可以做到极致的体验;哪些功能则是做了反而会影响核心体验,需要舍弃。 比如像COC,整个战斗,核心操作就只有放兵。肯定有玩家喜欢自己操作士兵怎样攻击目标,但是他不提供这个功能,这是一个非常创新的取舍。 再举一个例子,硅谷的公司,即便是那种创业的小公司,一开始做产品就是做Internationalization的,而很少去做Localization的工作。 比如说一个交互,他们只会做一种,不会说为了中国用户做一种,为了美国的用户又做一种,即便中国的用户和美国的用户在习惯上文化上有各种各样的差异。 这样有利于他们的产品在本土上线后,能够在不到半年的时间迅速往全球推广。做Localization短时间内能在某个局部的地区提高收益,但是从全局的角度看,增加了维护成本,反而得不偿失。 这样的思路其实也是一种取舍,专注核心功能,少做兼容,快速上线,不断迭代,值得我们去学习。
·代码质量
对于产品是否成功,代码质量并不是一个决定性因素。也确实有成功的产品,里面的代码写得很糟糕。但提高代码质量,对于团队的开发效率,维护成本,是有好处的。 团队合作编程避免不了阅读和维护别人的代码,阅读糟糕的代码不但影响工作效率,浪费大量工时,还非常影响心情。 相反,统一的风格,良好的命名规范,则能让大家阅读别人的代码就像阅读自己写的一样,降低心智负担,提高效率。 目前我们项目的代码规范是尽量往业界靠拢,术语的选定尽量简单易记,原则是简单,统一。避免过于严苛,因为那样反而会影响开发效率。 规范的问题在一开始的时候保持开放,让大家都参与并且达成一致认识,之后严格执行,这样早期就能建立起好的代码模板。后面招新人,团队扩大之后,因为加入新项目一开始写代码都是模仿的,代码质量也能有所保证。
·服务端技术
这部分从M项目说起。作为公司试水手游领域的产品,M项目的最主要任务是检验市场。 没有人能预测什么项目能成功,什么不能,我们能做的是不断地根据市场变化来调整方向,尽快让产品上线,根据市场作出反应,不断做迭代优化。 而技术选型则需要在立项之初拍板,中途变更的成本恐怕所有技术团队都承担不起。在这两个大前提下,选择现在这套mudos框架是非常正确的。 因为无论从业务类型、技术成熟度、团队技术经验这几个因素来说,mudos都是在有限资源下能让产品快速上线的最稳妥选择。最终M项目也因此能够以公司首款手游推出,吃了第一波最大的资源,获得不错的成绩。
但是,服务端的东西就是这样,做100个人用的系统,和做100万人用的系统,是完全不一样的。 M项目上线第一个月,服务端架构的问题就充分暴露出来,玩家纷纷表示服务器非常的卡。 我那时候做了一些优化,比如战斗加CD,把集中的逻辑打散,情况稍微缓解。 这些优化,很多只是规避了问题,并没有解决。因为M项目的架构是这样,逻辑和数据库绑死了,一个服务器的数据只能跑在某一台机器上,它没办法做伸缩。 也就是我想让更多的CPU给某些繁忙的服务器做运算,办不到,或者说很困难,很曲折。
而当时观察,最卡的服务器,在线玩家也就1000人。为什么同样的引擎,MH能撑1万8,而我们只能到1000? 原因很简单,因为MH的游戏类型和我们有本质的不同。MH是回合制的mmo,一个战斗过程进行得非常缓慢,所以计算量得以均匀分摊到所有时间点上。 M项目则不一样,整个战斗需要在一瞬间计算完成,典型的CPU密集型业务。假如某个时刻有100个玩家点战斗,那就是有100个CPU密集运算请求,而逻辑又是单线程,可想而知有多卡。
回到我们项目,像RTS这种游戏类型,如果我们继续用纯M项目的框架去做,肯定是不行的。必须额外写一个战斗服务器,让这些CPU密集型的运算分出去,做到可伸缩。
新引擎其实在可伸缩这块做得更彻底,因为它是逻辑和数据分离的。整个框架,是一个分布式架构,连数据库这个所谓的“单点”,其实它内部也是分布式的。 玩家从数据库load到哪个游戏进程,事先是不知道的,由引擎内部的一些负载均衡策略决定。 所以玩家属于哪个服务器,本质只是身上的一个变量,是一种逻辑的概念,而不是原来那种物理的概念了。 这样子,理论上只要有足够多的机器,一个服务器的人数是没有上限的,搞世界同服都可以。玩家之间的简单交互,比如聊天,通过网关转发;复杂交互,比如战斗,则先迁移到同一个进程,在进程内对象之间的通信就非常简单了。
除了架构,新引擎的另一个优势是脚本语言,它本身是Python写的,维护起来相对简单。可扩展性高,其他很多工具都有Python接口。 客户端也是用Python做脚本,这样程序员开发功能就可以两边都做了,减少语言转换带来的负担,提高开发效率。
所以抛开最初的学习成本,我们的游戏类型应该说更适合使用新引擎来实现。
这一年依然非常感谢每一位一起努力的同事,虽然旧项目在没落,但是新项目在诞生。 这是一个从头做起的项目,真正的考验,才刚刚开始。只有坚持下来,才能有所收获。希望明年新产品成功上线,能够写一些东西,和大家分享。
2016年1月