会变形的模块 之二

来源:互联网 发布:c语言头常用头文件 编辑:程序博客网 时间:2024/05/07 20:47

话题回到游戏开发领域。我们解决新问题时,经常会用我们已经熟识的方法。比如开始写一个游戏引擎——我们暂且把做游戏还是做引擎的问题放在一边——经常会从底层开始写,于是先写平台抽象,然后是图形、声音、网络,之后才开始写游戏核心,高层的模块依赖于底层的模块。这看似没有问题,你说呢?

 

问题一:从敏捷方法来看,这个引擎从开发到能跑起来的周期太长了,到整合时会有一个bug大爆发时期,会发现模块间有各种各样的需求不匹配问题,需要大量的返工。需求总是不明确的,很多问题只有到使用时才会发现,当最后做游戏核心时,才会发现原来的图形模块设计少了这种那种的功能,而这些功能需要对图形模块从结构上做修改。

 

问题二:写底层模块时,由于还没有使用者模块,很多需求只能基于猜测或看别的引擎有什么,往往会导致设计得过于通用,花了很多时间做了很多不需要的功能,优化的方向和最终的需求不一致。

 

简单说来就是在没有实践检验的情况下容易产生过少设计(under-engineer)或者过度设计(over-engineer)。不如先尽快把架子搭起来,让游戏先跑起来,再添砖加瓦,在问题和需求明确了的情况下,再考虑重构。就像乌龟换壳、蛇蜕皮一样,让架构和引擎一起成长。

 

问题三:普遍的观念是底层比上层稳定,但有时未必如此。3D显示技术每年都翻新,可能比游戏核心变得还快,而且每隔若干年还会有一次结构上的大变,比如D3D9D3D10,即使已经抽象了图形接口,仍然会导致一定的结构调整。如果连没有抽象层,则游戏核心都得跟着改。

 

地狱之门伦敦在07GDC展示的从DX9DX10的移植就是这样一个例子,虽然作为成功的移植范例。他们的游戏是直接在DX9上写的,往DX10移植时,只能通过typedef、宏和模板函数把DX9的符号抽象出来,变成和版本无关的符号,然后用#ifdefDX10下使用DX10模拟的DX9 API。虽然算是移植到了DX10,但程序结构依然是DX9的结构,因为DX9的用法和结构已经遍布游戏核心,很难分离开了。

 

当然,也不是说抽象底层模块是唯一解决之道,设计一个好的抽象是困难的,除非你的需求很低,只需要通用功能的子集。问题的关键不在于是否做了抽象,而在于是否做到了“原则一:复杂性局部化。”显示输出,说到底不过是游戏的输出部分而已,即使没有显示模块,游戏核心应该一样可以跑。Unreal05还是06年的GDC展示的组件化实体设计(Component-based Entity)就是一种方法,显示组件作为游戏实体对象的一个可选组件,只有该组件的源码才引入图形API的头文件,在客户端运行时添加该组件,在服务器端时则不加该组件。即使图形API需要重构,其影响最大也只到显示组件而已。

 

原创粉丝点击