9月23日,首届“梦想·匠心”腾讯游戏开发者大会于深圳举行,在技术分论坛上,腾讯互动娱乐《天涯明月刀》项目技术总监张正分享了《天涯明月刀》的后台技术创新。拥有15年游戏从业经验的张正,于08年加入腾讯,先后参与或主导《轩辕传奇》、《天涯明月刀》等大型MMORPG项目的后台开发。张正于本次论坛上讲述《天涯明月刀》服务器开发中的技术深度探索,在业务复杂度控制、性能及承载、系统高可用等方面的创新性技术方案。

142505lg4u95lae0vcuzv5.png
以下内容为演讲实录:

接下来由我给大家带来分享,我分享的题目是《天涯明月刀后台开发的技术创新》。我是腾讯互娱北极光工作室群后台技术中心总监张正,我加入腾讯接近10年,从2004年开始做游戏后台开发。从2011年加入到《天涯明月刀》,做到目前为止,做了6年半左右的时间。

142506l2hikc3wqlwvvzhd.png
《天涯明月刀》的用户还是很多的,但现在市场逐渐往手游倾斜,所以很多人可能还是不了解市面上端游的产品。《天涯明月刀》可以说是近两年腾讯公司在端游上的标杆,这里主要介绍技术方面的特性。《天涯明月刀》是非常大型而复杂的端游项目,我们在服务器端手写代码的规模就已经到150万行,其中像我们最核心的场景进程,单进程手写代码超过50万行,复杂模块代码量到10万量级,像技能、移动相关的。天刀服务器单组同时在线可以到4万,这是线上实际达到过的,而不是停留在设计容量中的。关于性能方面,单核的承载可以到千人左右,这时技能的释放非常频繁,而且不断有强交互、位移这些出现。另外,说一个比较特色的技术点,天刀的服务器地形是真正的3D,在大型MMORPG里面是一个挑战,后面我会详细展开讲。我们7月份推出了航海资料片,里面的海是非常大的,64公里见方的范围。

《天涯明月刀》后台技术的创新路径

来看创新的定义,有别于常规的思路,为了满足需求,找到新的路径和新的方法。天刀在服务器技术方案上怎么样找到新的路径?主要通过三个方面:一是通过技术提升玩法设计。二是游戏体验方面做极致的优化。三是运行质量、稳定性方面追求更高。


《 天涯明月刀》后台真3D技术

142507azf2ugfh2u5q64uk.png
先来做一些类比,比如有一款3DFPS的产品:FPS里面有爆头的设定,打到身体包装盒覆盖的地方需要有特定的伤害。FPS游戏的房间里面的人数是比较少的,大概20来人左右,另外地图比较小,应该是在几百米的范围内。它用的技术方案是在服务器端运行UE3。另外一款是3D骑砍项目,里面会有140人的对战。技术方案和前面略有不同,是用Havork引擎在server上面跑,也是以开房间的模式。

天刀在服务器做3D化时会存在哪些挑战?天刀的特点和早年间的MMORPG不一样,那些游戏的技能释放频率比较低,更多是站桩打。天刀作为一款ARPG游戏,打起来的节奏非常快,攻击方和受击方都要边打边移动。另外我们的地图很大,产品设计之初就确定为产品的特点或者优势,边长4公里,单张地图的大小达到16平方公里。从MMOPRG玩家的角度,他们对精度的感知更低,所以我们无需采用前两者那么高精度的方案. 为了让玩家在游戏内自由迁徙的同时,服务器各个场景的负载还是能够做到比较好的均衡,我们把每个场景都加载了全部的地图资源。天刀的单张地图有16平方公里这么大,精度还需要到单个碰撞格子0.5米,所以单张地图的数据量非常大,五六百MB一张地图,全部加载之后达到7GB。

早期的时候,天刀服务器是传统2D方案,首先我们想到的,是把平面变成多层,2D本来是XY的网格结构,用很多层的网格结构,似乎可以构建3D的世界。但是后来发现这样不行,它会有很多复杂情况处理不了,比如一楼和二楼之间架楼梯,楼梯算几层?而且有些楼梯在塔里面,是盘旋楼梯,那就更难处理。另外策划需要刷怪或者刷物品,在编辑器里面需要处理刷上去的每个怪或者每个物品放在几层, 这就变得非常复杂。所以后来我们想到一种方案,我们受到voxel体系的启发,在编辑器里用voxel把世界描述出来,经过一些处理最终得到右边的基于voxel的3D场景描述。简单说,垂直投影到一个平面上还是XY,但是在Z轴的方向,垂直的方向,相当于有高度、有层的概念。

场景碰撞校验算法

142507c0j76ff6ud3nn3tz.png
从剖面图上可以看到最低处绿地都是0层,我们从某个0层格子往上看,投影上有一个实体,我们认为这里1层,再往上是2层;如果中间没有这个实体,就是从0层到1层。

这样的话,上层业务逻辑来调用时,先做行走路径的碰撞,当然首先检查有没有静态阻挡,接下来做高差的判定,可以直接走上去的高差阈值应该是在1.5米左右,人的身高在1.8米。接下来做碰撞判定,如果空间非常矮也走不过去。对于飞行是单独走飞行判定,需要判定往前飞会不会被挡住,以及飞过去的空间是不是可以容纳。

回到前面说的问题,单张地图这样描述,会导致数据量很大,大到600~700MB,我们针对这里做了很多的优化。首先是空间的优化,我们单独做了一个内存的共享。它的额外好处是可以提升服务器的加载速度。因为单个物理机有很多核,产品的进程都是单线程的架构,我们需要多个场景分别启动,每个进程都去读几G的地图数据,这样启动非常慢。如果先有一个进程把地图加载到shm,其他的进程都直接attch上去,这样速度就会快很多。我们还做了时间的优化,单个Grid上可行走的方向是4个,两个相邻格子之间的联通关系都是静态确定的,不需要运行的时候一遍一遍判定,所以我们做了联通性的cache,在运行时cache的命中率可以达到95%。

最终做了这些工作我们可以得到很好的性能,大家可以看到,移动每秒内的耗时在140毫秒,即便把移动加上技能AI都调用位移相关的逻辑,加在一起,我们行走层相关的计算也会在20%的CPU消耗以内,应该说是非常可以接受的数据。

「沧海云帆」资料片超大海洋实现

以上说的基于voxel的方案是2014年以前做到的。到2017年的时候,策划表示我们加一个航海的玩法吧,接下来我介绍一下航海玩带来什么样的挑战。

142507xq09re11c0rp16pc.png
简单回顾前面voxel地形,大小是0.5米,我们用的视野管理是非常经典的九宫格管理方式,我们把每个格子叫一个Around,边长54米。

航海需求下出现这样的问题:首先是航海的地图,我们要求它要非常大,因为有船的航行速度摆在那儿,不能说开一小会儿就到地图边缘不能走了,这样体验就非常假。最终我们定了一个大小64公里的航海地图,是原来地图的256倍。对于对象的碰撞检测,原来无论人还是怪,我们把它设为一个点,不在这个格子上、就在下一个格子上,只用检测一个voxel或者相邻的4个voxel就可以。但船只非常大,50米乘以20米,也就是100×40个格子,总共4000个格子那么大。这样就会带来非常大的问题,如果大家有在MMORPG的格子地形上做过多格对象,就知道这样的设计非常复杂,而且开销非常高。正常的视野,九宫格的边长相当于54×3,也就是162米。但开船在海面上,视野很大,这个视野会到3000米那么远;陆地与海面并存,你开船时会看到前面的岛,然后可以下船来到岛上去,像真实的在海上一样。当然你在岛上办完事还可以继续开船。内部讨论时,我们一开始问,能不能进到一个岛,就刷一个副本,画面一闪就进副本,副本刷完再从岛里出来。但这个体验不是足够好。我们也想过更为简单的方案,在服务器侧,因为船那么大,相当于一个房间,玩家在房间里搞来搞去就可以,客户端上看到的是船在动,但是服务器上所理解的是海在动,而房间是固定的。

最终,我们还是想挑战一下更好的技术方案。比如在保持voxel的精度不变的情况下扩展地图。但这样直接带来的问题是单张地图的内存就会成倍往上增,会到50G的规模。第二个方案:是不是可以把精度搞得粗一些,但对于海岛来讲,阻挡就不能做得非常精细,岛上的视野管理也会出问题,单个around会变得非常大,广播就会成倍往上增。第三个容易想到的是无缝地图,无缝地图甚至可以被当做包治百病的方案。但我们已经走在了voxel的路上,每个场景单独隔离,每个地图对应一些副本,切地图的时候,它就会切进程或者副本对象。如果往无缝地图改,风险是很高的。另外和上层之间的交互变得和以前完全不一样,以前一个地图肯定在单个进程里面,现在一个地图分成很多块,每块在不同的进程里面,从一小块走到另外一小块就要迁移到不同的进程去,这里会涉及到一些事务的处理,特别是船走着走着,船头的人在进程A,船尾的人在进程B,会非常复杂。

142508rntfayvtrqqvevqf.png
最终我们找到一个方案,说是折中方案也好,复合方案也好,就是双精度地形。大地图用粗精度描述: 海其实和地面还是不一样的,地面上总是会有盖房子、立柱子,人穿不过去。海面除了岛以外,大部分的地方都是可以通行无阻的,所以地形细分粒度不需要很小。海岛的地形和普通地图一样,还是基于0.5米见方的格子组成的,我们把它作为插件融合到大的航海地图里面去。

我们做了分层的视野管理,航海地图用了边长很大的around,在岛边缘的时候做切换。这个方案的优点是可以满足几乎所有的要求,比如对视野的要求,对地形精度的要求,包括内存占用。刚才说海的地图,本身并没有多少需要描述地形的数据,改动局限在地图碰撞和视野管理的底层,对于上层的逻辑就可以直接像原来一样该怎么用就怎么用。视野的范围,大地图发生的行为要广播到周围的around,周围如果有海岛,会把消息推给海岛。如果海岛和海面的交界发生事情,这里会有一个底层边缘升格的策略,把边缘的事件广播到周围的海图上去。

看一下这个混合方案在技术维度上的结果。在空间复杂度上,虽然一张海图还是被整为一个文件,文件大小只是增加到了4倍,地图却是原来的256倍那么大。时间复杂度上,其实并没有非常明显的增加,在视野管理上同时满足了海岛上的视野管理和海上的视野管理,并且两者之间是可以有非常好的无缝切换。

这是天刀上线前后的一个slogan,你想要的必将实现。无论是策划团队还是技术团队,我们都希望给玩家打造最好的游戏体验。

《天涯明月刀》千人群战优化

142509ungodpl10xxkg5de.png
142510xznv8rnlavifoa5i.png
这是天刀640人盟会争锋战,在同屏里看到的玩家很多。第二张图是800人的修罗城,在刚上线的时候,由于和策划团队之间缺少提前的沟通,当时面临一个非常被动的情况——这个玩法在某些服灰度上线了, CPU一直在100%,延迟达到10秒,相当于完全卡住不动,我们称为雪崩。

142510p0v0lb3z37habba3.png
优化面临着非常大的困难,我们的代码复杂性比较高,前面提过一些,比如代码量非常大,单个核心模块非常复杂,它是动作性的游戏,而且技能由很多子技能复合在一起,天刀的技能系统策划不只配表格,还可以在里面嵌脚本。我们已经在运行时把配进去的脚本转化为C++的数据结构执行,但是即便如此,单技能的消耗还是非常高的,有2.5M CPU周期。业务复杂性上,也不能说玩法设计太,但是最终达到的情况就是这样,玩家的聚集非常密集,150米见方聚集了800个人,因为天刀开始希望打小怪爽快一点,给每个职业都设计了AOE的技能,又因为是武侠动作游戏,所以公共CD很小,技能释放很频繁,每个人都使劲放技能,每个技能都可以打到周边一片人。参与人数每增加25%,负载增加56%,这是经过实测和测算的,对应我刚才举的例子。

142510h9k56g90b6jlnj5n.png
天刀里面有哪些主要的模块在提供复杂度和性能消耗?主要是移动、战斗、数据同步和AI。在战斗方面我们分析下来,最主要的几个消耗:目标扫描,因为AOE技能多,目标扫描里面又需要判断目标和自己之间各种各样的关系,像这种大型MMORPG游戏里面,很多模块会产生敌我关系判断的影响。连通性检查,前面提到基于3D的地形判断上面,比如远程技能能不能打到目标,中间隔了许多格子要去计算。静态修饰是指,每个技能在释放过程中可以被很多的buff影响,如果有某个天赋,可能技能过程就变了。另外动态上了buff,或装备特殊装备和特殊武器,技能就可以发生变化。

统计下来所有业务开销,技能在里面占了接近60%,但是技能系统相关代码的行数是10万量级的,技能的数量也非常多,光主角技能就是几百的量级,我们逐个解决是不太可能做到的,更无法短时间内做到。再看技能吞吐量,那时候能支持的吞吐量大概是在400人、每秒500个技能,在800人的时候,期望每秒释放的技能数要上千。实际还没到一千系统就过载了,所以首先要做的事情是把过载解决掉。我们建立了防过载的体系,把CPU去做压力分级。有内置探测CPU占用率的功能,如果CPU达到了50%以上,就开始触发降级的策略,让逻辑模块的服务内容做一些降级,比如AI的思考频率低一点,允许释放技能的频率低一点。到90%的时候就要触发过载保护,过载保护后面展开讲。真正系统压力高企的时候,很多模块的策略就会发挥作用。

我们为技能做了这样的策略:技能有配额池,每释放1个技能就从配额池里面提取1个配额,每过1秒会重置这个配额。重置有一点问题,是到底重置多少。前1秒如果有1000个配额,把CPU跑满了,下1秒我们会让配额快速下降,直接减半。这样CPU就可以快速降下来,之后我们就逐渐再把配额升上去, CPU占用率越高,我们给它往上升的比例越低。一开始从过载的状态迅速把配额降下来时,玩家体验会变得非常差,差的表现是连按12345滚键盘但技能放不出来,逐渐把技能配额升上去以后,玩家体验就会逐渐恢复。

其他模块降级的策略会有AI思考间隔,移动请求降频,技能扫描的范围,有些AOE技能打得很远,在系统非常繁忙的时候就不让它打到那么远,只搜索附近的玩家。做了过载保护以后,有这么几个成果,系统已经不是一直维持在过载状态,像聊天、移动就可以变得流畅了,但是技能的延迟还是非常高。CPU曲线会出现狗牙状,非常不稳定,还在不断的往顶上碰,上去以后就会被砸下来,之后又会由玩家行为顶上去。

142511h346t3keidigniig.png
前面通过过载保护让系统能够喘口气,之后我们想怎么优化。

· 实现层优化的方法比较常见,像空间换时间、变化比较少的结果放缓存,降低重复计算。另外可以用性能分析工具找哪些函数消耗最高,或者哪些消耗偏高的函数看上去不合理。

· 业务层分两个方面,这是腾讯内部经常提到的海量服务策略,像柔性可用,我们设计几个级别的服务,像刚才讲的反馈模型一样。另外可以做一些有损服务,比较经典的说法是玩家渴了,但是他说想喝果汁,我没有果汁时给他水喝,也可以很大程度上解决问题。

· 架构层,我们也可以做一些工作,按照功能纵向切分,把旁路功能切分到独立的进程里去,还有, 业务无关的网络IO包括打解包都放到独立的线程里面做。另外也可以在架构层做横向切分,比如把负载调整得更好。


《天涯明月刀》业务层优化

142511n2kywp4rfdxfqhqg.png
我们还是从业务的角度对群战问题做分析。在释放频率上,大概0.8秒就可以放1个技能。小范围里有这么多人的情况下,玩家虽然很在意我是不是卡,但是不在乎技能应该打到的精确目标。比如周围有ABCDE,而C没有打到,他不太能感受到。战斗策略方面,那么多人聚在一起互相砍的时候,他们更想看到的结果是我放技能,旁边的人死了。到底伤血次数有多少、每次的伤害值,他并不关心。而单独打斗就对于技能的表现,对释放频率,对一边打一边跑这样的东西很敏感。然后看技能喜好,我们给每个职业都设计了比较好用的AOE技能,经过统计发现,其中有一些消耗占比很高。它们的共同点是攻击范围都是AOE,类型均为高频EOT(随着时间生效的技能),比如太白的无痕,3秒生效30次,还有归玄频率为2秒10次,这都是非常频繁的。我们得出的思路是利用这样的业务特点,利用玩家的体验倾向,对重点技能做针对性的优化。

最终可以得到技能优化专用版,对技能原来每秒10次、每次20点伤害,可以压缩成每秒1次,每次伤害200,也就是说降低频率、提高单次效果。另外策划可以自己做一些简化,原来有些技能的跳转是非常复杂的,简化后逻辑效果仍然和原来持平。

143238bhhphosllp5505h5.png
有了这样的专用优化版技能,感觉可以松口气,但还有额外的问题。比如,我们的地图很大,地图这边可能会有一千号人凑在一起猛打,但是另外一边就会有人插旗单挑,或在单对单PK,这种情况下玩家是非常在意技能效果到底是不是那么真实的,因为他这时候只有一个目标。另外,单个场景进程里面会有多张地图实例,如果群战地图用技能的优化版本导致副本地图里也受到影响,这是不能被接受的。 我们需要准确的识别群体行为。

来看怎么试图识别地图上的热点区域。基于around里的人数和技能释放频繁度,我们可以把around标记成热点区域,在区域里用专业的技能优化版本。还有热点漂移问题,在群战里面玩家一边打一边跑,热点就会往下面的around移过去。形成热点需要若干秒的统计累积,这种情况下就会出现毛刺,尤其战场在格子边缘,不断来回拉扯的时候就会更容易出现毛刺。我们用热点延迟降级方法解决了热点漂移的问题。这样玩家在且战且走的时候,它的技能的计算性能是平滑的。这个优化以后技能的开销呈量级往下降,而且技能的切换是平滑的,玩家几乎无感知。

143239tmtao76eumm7pg7a.png
做了业务层的优化之后,大家可以看到CPU曲线已经是比较平稳的状态, 800人混战CPU占用50%左右,支持千人规模的群战是没有问题的。

《天涯明月刀》后台逻辑层可用性提升

最后说一下后台逻辑层可用性提升,我们怎么样在常规的可用性保证上又做了更多加深的工作。 腾讯自研的项目,凡是有状态的进程,要把很多的上下文数据分配到shm上,作用是, 一旦发生crash,我们可以重新拉起进程执行体,把shm数据重新加载上去,然后基于原有状态往下跑。这样数据并没有丢掉,听上去很美好。

但是这样的方案还是存在一些问题,相信很多项目都有遇到过。因为真正导致进程宕掉的故障点可能还在,可能再次触发。resume要求拉起来很快速,具体体验上,玩家可能感觉卡了几秒,然后又可以继续玩。但天刀的进程里状态数据很多、使用内存很大,人工判断一下故障点再让进程拉起来是不可能的。

143239krdesrr3dderqsps.png
前面提到了故障点,接下来我们对故障点做一下分析。 MMORPG进程的驱动力之一,数据包,无论玩家请求还是内部进程请求或回复,都可以认为是数据包。驱动力之二, 定时器,时间到了就执行定时器里面要求的内容。驱动力发生错误还好处理,在重新起来的时候可以把驱动力扔掉。比如resume后会略过之前的timer,跑下一个timer。再看驱动力之外的因素,所有的程序其实都是逻辑加数据,如果维护的内存数据出现问题,进程也会产生异常。我们很自然的想到做自动检测和隔离,隔离一些数据,也可以隔离一些逻辑。因为逻辑如果频繁造成resume,玩家也不能玩。比如他进行一个操作发现卡了,就又再试,一直试,然后这个进程就不能用了,这样的情况我们也希望隔离。

但是隔离的时候算法不能太复杂,要保证速度,又不要出现难以追查的错误。

我们建立了故障点自动检测和隔离的系统,核心是有两个过滤器,驱动源的过滤器和数据源的过滤器,所有的驱动力来了,要检查能不能从过滤器过去,过去以后才能跑;对象也需要每次访问的时候看在不在过滤器里面。(图上)这里是非常小的数据结构。我们把运行时用到的东西放在记录列表里面,resume的时候触发分析。尽量做最小粒度的隔离,包括数量的粒度和对象层级的粒度。其实这个系统刚上线的时候出现过故障,我们把一个帮派对象隔离掉了,结果和这个帮派里所有玩家都认为自己没有帮派了,而且把这个信息存盘了,于是造成更大的故障。到后来我们设置了一些白名单,有些类型的对象是可以被放到隔离区的,有些东西如果真的非常大、非常复杂,和其他地方耦合度很高,我们还是倾向于其他处理方法。下面是最后实施的效果(见PPT)。在版本更新、解决整个故障之后,再手动清空隔离内容。

143239v4n9fvdlnjlr0ra5.png
回到我分享的主题,我们的创新路径是这三个点,具体展开,就是3D地形和航海、千人群战优化,以及resume的加强版。

我有时候会想,如果站在2011年看现在天刀后台做到的东西,真的会觉得还是挺厉害、挺精巧、挺新颖的。同样,在2011年的时候去看现在的一些电子产品、电器产品,我们也会有这样的感觉,感觉真的是一个完全新的东西,但这是靠不断的探索、不断的积累,最终才达到了现在的高度。

最后跟大家分享苹果的设计总裁Jonathan Ive说的话,想做得不同很容易,但是想做得更好非常难。希望我们天刀能越做越好,给玩家提供更好的体验,也能给大家今后带来更多更好的分享。

我的分享到此结束。谢谢大家!
 



QA环节:

提问:刚才说千人PK,客户端怎么处理,真的800人在客户端同屏可见?

张正:可惜我们客户端技术专家今天没有过来,我们知道天刀客户端的优化应该是国内市面上接近次时代级别里最好的,客户端的群战显示比较早期就做到200多,不过我不确定最终的数字是多少。

提问:不会裁减一部分人,然后客户端不可见?

张正:极限情况下会有些人只有名字。在天刀客户端,主角有很好的表现,它有各种各样的布料,特别是丝绸有多层,基于物理甩来甩去,很好看。但是渲染第三方是打了一定折扣的。另外群战的时候技能特效也会做一些降级。

提问:有的游戏,比如我们的游戏是选择这种策略,一千人站在一个位置,理论上大家互相可以见到,但是我们会强制卡掉一部分人不可见,这样可以减轻客户端响应压力。但是这么做之后带来的问题是你需要自己设计一套规则选择到底要哪些人客户端可见,是这个策略,我以为你们有这方面的做法,是有什么策略,但是听你的意思好像没有。

张正:你可能更多问的是流量优化的问题。我们做了多级的网络同步,可以从多个维度分级。比如首先发玩家的摘要,因为发200个人的全属性同步是很困难的,但是发200个人的ID、名字、职业就很容易。有些关系比较近的,可以发更多的信息给他。客户端收到摘要以后,可以自主请求详细信息, 这里就需要做服务器端请求频率、请求量的控制。另外服务器也可以做cache,因为玩家的外观变化是非常慢的。

提问:voxel到底是正立方体,Y向也是0.5米,还是Y向长度不一样?如果是0.5×0.5×0.5,有些处理结构比较容易,但是外根据遮挡情况是可变的长度,可能处理复杂一点?

张正:单纯讨论voxel的概念就是0.5米见方的立方体,我们在编辑器里做地图数据的预处理的时候,首先会把它voxel化,这时整个世界就是用小方块垒起来的。但这样voxel的数量很多,最终得出来的数据量很大,所以可以把这些相连的voxel合并成柱体,这个世界由柱体组成,一格水平投影上可能有多个柱体。

提问:0.5米的精度是否够,是否让实际障碍和0.5对,这样实际精度的问题会少一些?

张正:精度是有实操经验才会问到的,的确可能有这样的问题。,比如我开始在轩辕项目用的是104厘米,在做比较精细的地形的时候,就显得精度非常差,看上去是圆的转弯,但不能尽量贴近它。天刀项目里,我们尝试之后,最终在50cm上取得了一个比较好的平衡,当时我是挺建议选64厘米这样的值,但是美术和客户端以及我们的编辑器这边都倾向于用50,这样粒度会更小一些,人计算起来也更方便。在我们的场景编辑里摆物件时,房子和格子可以是平行的,也可能斜着放,我们试验过之后认为这些情况下的表现都是OK的。另外,客户端也可以做一些显示上的优化,像孙勋讲的一样,表现和逻辑做一定程度的分离,在客户端看到人紧贴着一面斜着放的墙,但逻辑层的位置以及服务器的位置离墙还有一段距离。

提问:之前提到有些会用物理,你们用voxel是因为觉得物理的数据量太大吗?

张正:还是性能问题。Voxel方案把地图和碰撞离散化成这样,我们在处理千人群战的时候还是这么费力,如果在真正的物理世界里去折腾的话,就更不可想象了。

锐亚教育

锐亚教育,游戏开发论坛|游戏制作人|游戏策划|游戏开发|独立游戏|游戏产业|游戏研发|游戏运营| unity|unity3d|unity3d官网|unity3d 教程|金融帝国3|8k8k8k|mcafee8.5i|游戏蛮牛|蛮牛 unity|蛮牛