目录

Game-Engine-Architecture-by-Jason-Gregory1.6-实时游戏引擎架构

目录

Game Engine Architecture by Jason Gregory:1.6 实时游戏引擎架构

一个游戏引擎一般是由工具集和一个运行时组件组成。下面部分我们将首先研究这个运行时组件,然后再看工具集。

图片1.11展示了组成一个典型的3D游戏引擎的主要的组成部件。没错,它非常宏大!而且这张图片并没有把所有的工具都包含进来。游戏引擎绝对是一个大的软件系统。

就像其它所有的软件系统一样,游戏引擎是分层次结构的。一般来说上层依赖下层,但反过来不一定成立。当下层也依赖上层的时候,我们就说这是一个循环依赖。循环依赖在所有的软件系统中都是需要尽量避免的,因为它们导致系统联接关系不明,让软件变得不可测试,阻止代码重用。这个对大规模系统如游戏引擎尤其正确。

http://hi.csdn.net/attachment/201103/7/0_1299512382mPzG.gif

图片1.11 Runtime game engine architecture

现在是图1.11中对话框中描述的组件的一个概览。本书剩下的部分将对这些组件进行一个更加深入的探讨,并学习这些组件如何被整合成一个功能齐全的完整的系统的。

1.6.1 目标硬件

目标硬件层,在图1.12中单独列出来的,是将运行游戏的电脑系统或者主机。典型的平台包括运行Windows或者Linux的PC,苹果iPhone和苹果电脑,微软的Xbox和Xbox 360, 索尼的PlayStation,PS2, PSP, PS3,任天堂的DS, GameCube, 还有Wii.这本书中大部分主题都是平台无关的,不过我们将会讲到一些针对PC或者主机的不同设计上的考虑,在某些有比较大的差别的地方。

1.6.2 硬件驱动

如图1.13描述的一样,硬件驱动是比较底层的由操作系统或者硬件开发商提供的软件组件。硬件驱动管理硬件资源,把操作系统与引擎上层跟无数不同的可用的硬件细节操作隔离开来。

1.6.3 操作系统

在PC上,操作系统是一直运行着的。它指挥着多个程序在一台电脑上运行,其中就包括你的游戏。操作系统如微软的Windows采用时间片的方法来让多个运行程序分享硬件资源,这个就是广为人知的抢占式多任务(pre-emptive multitasking). 这个表示一个PC游戏永远不能假定它对硬件有着完全的控制 - 它必须跟系统中的其它程序“和平共处”.

在主机上,操作系统一般只是一个很小的直接链接到你的游戏运行程序的库。在主机上,游戏一般完整的“拥有”整个硬件。不过,根据Xbox 360和PS3的介绍,并不是严格的这种情况了。例如,这些主机的操作系统可以打断你的游戏的运行,或者取得某些系统资源来显示在线信息,或者允许玩家暂停游戏,调出PS3的Xross Media Bar或者Xbox 360的dashboard。不管怎样,所有主机和PC上面的开发的差别在慢慢的缩小。

1.6.4 第三方SDK和中间件

大多数游戏引擎都使用了许多第三方的SDK和中间件,SDK提供的或者或者接口一般称之为应用程序接口(API).我们来看一些例子.

1.6.4.1 数据结构和算法

如同其它任何软件系统一样,游戏也非常需要一堆数据结构和算法来帮助处理。这是一些第三方提供的这些功能的例子。

  • STL. C++标准模板库提供了大量的代码和算法来处理数据,字符串和I/O流

  • STLport. 这是一个轻量级的简化过的STL的实现版本

  • Boost. Boost是一个强大的处理数据结构和算法的库,被设计成STL的风格。(在线的Boost文档还是一个学习计算机科学的好地方。)

  • Loki. Loki是一个强大到让你头痛的通用编程模板库。

游戏开发者在是否在引擎中使用模板库如STL上产生了分歧。有些人觉得STL的内存分配模式并不高效并导致内存碎片(看5.2.1.4节),这使得STL在游戏中不适用。另外一些人觉得STL的强大和方便足以掩盖它的缺点。而且事实上大部分问题都可以解决。我的个人意见是STL在PC上面使用是没有问题的,因为它的高级的虚拟内存机制对于小心的内存分配不是那么严格(但仍然需要小心)。在主机上,由于受限的或者根本就没有虚拟内存机制,还有昂贵的cache miss开销,你最好自己写一个具有可预测的或者极少内存分配的自定义数据结构(在PC项目上这样做的话也不会错到哪去).

1.6.4.2 图形

大部分游戏引擎是建立在这些硬件接口库上面的:

  • Glide. 这是一个给老式Voodoo显卡的3D图形SDK. 它在硬件坐标转换和光照加速(hardware T&L)也就是DX8出现的时代非常流行。

  • OpenGL. 一个广泛使用的轻便的3D图形SDK.

  • DirectX. 微软的3D图形SDK,OpenGL的主要竞争对手。

  • libgcm是一个底层的直接面向PS3的RSX显卡的接口,是索尼提供的一个比OpenGL更高效的选择。

  • Edge是一个由Naughty Dog还有索尼为PS3提供的强大的渲染和动画引擎,它被许多第一方及第三方游戏工作室采用。(译者按:第一方工作室,first-part studio,与某家游戏机制作商签约的专门为他们制作游戏的工作室)

1.6.4.3 碰撞和物理

碰撞检测及刚体物理(在游戏开发交流中简称为“物理”)由下面这些有名的SDK提供支持:

  • Havok. 一个非常流行的工业水准的物理及碰撞引擎

  • Phy X. 另外一个具有工具水准的物理及碰撞引擎,可以从NVIDIA那免费下载。

  • Open Dynamic Engine.(ODE) 是一个非常流行的开源物理/碰撞模块。

1.6.4.4 角色动画

这里有许多商业的动画包,包括但不限于:

  • Granny. Rad Game Tool的非常游戏的Granny toolkit包括了能支持所有主流3D制作软件包括Maya和3DMax的性能优良的3D模型及动画导出插件,一个能读取和操作导出的模型及动画数据的实时库,还有一个强劲的运行时动画系统。在我看来,所有商业的或者私有的库中,Granny SDK有是最着最好的设计及最符合逻辑的动画API,特别是它对时间的天才的处理。

  • Havok Animation. 随着角色变得越来越真实,物理及动画之间的界线变得越来越模糊。那个开发了游戏的Havok物理SDK的公司决定制作一个免费附送的动画SDK,它使得物理及动画之间的连接变得从未有的简单。

  • Edge. Edge库是Naughty Dog的ICE team为PS3开发的,他们是Sony Computer Entertainment America的工具及技术团队,Sony在欧洲的高级技术团队开发了一个强劲的高效的动画引擎,还有一个为了渲染的高效的几何处理引擎。

1.6.4.5 人工智能(artificial interlligence, AI)

  • Kynapse. 一直到最近,人工智能一直是由每个游戏自定义的。不过,有家叫Kynogon的公司制作了一个中间层的SDK叫作Kynapse.这个SDK提供低级的AI模块,包括寻路,绕开静态和动态的物体,发现某块区域内的弱点(例如,某个开着的窗户可能就是埋伏的好地方),还有一个合理的关于AI及动画的接口。

1.6.4.6 生物的角色模型(Biomechanical Character Models)

  • Endorphin and Euphoria. 这些是用真实人类移动的高级生物模型制作的角色动画包。

我们在前面提到过,角色动画及物理之间的界线越来越模糊。Havok Animation这种工具包试图把物理和动画通过传统方式结合起来,也即是通过Maya这类工具做出用真人动画来提供主要的动画,而通过给出物理参数进行实时的运算。不过最近一家叫做natural Motion Ltd的公司制作了一个产品试图重新定义游戏中或者其它数字媒体中如何处理角色动画。

它的首款产品,Endorphin,是一个Maya插件,它允许动画师对角色进行完全的生物模拟并导出就如同手动动画制作一样的结果。这个生物模型计算重心,角色重量分布,以及一个真实的人在重力及其它作用力影响下如何保持平衡及移动的细节。

它的第二个产品,Euphoria,是一个Endorphin的实时版,它试图产生在不可预测作用力影响下实时的精确的物理及生物动画。

1.6.5 平台无关层(Platform Independence Layer)

大多数游戏引擎需要有能运行在超过一个硬件平台上的能力。像EA及动视暴雪(Activision/Blizzard)这些公司,一直把它们的游戏定位在一个非常广泛的平台,因为这能使他们的游戏拓展到尽可能大的市场。典型的,对每个游戏,唯一不把目标定在至少两个不同的硬件平台上的公司是第一方工作室(first-party studio),如Sony的Naughty Dog还有Insomniac Studio.因此,绝大多数游戏引擎架构上都有一个平台无关层,如图1.16所示。这一层建立在硬件层、驱动层、操作系统,还有其它第三方软件上之,把引擎的剩余部分和大部分的底层平台细节隔离开来。

http://hi.csdn.net/attachment/201103/8/0_12995996509tQY.gif

图1.16 Platform Independence Layer

通过封装或者取代最常用的C标准库中的方法,操作系统调用,以及其它的基础的API,这个平台无关层保证引擎在所有不同的硬件平台上的行为一致性。这个是必要的,因为不同的平台之间有很多差别,即使是C“标准”库。

1.6.6 核心模块(Core System)

每个游戏引擎,还有每个真正的大的,繁杂的C++软件程序,都需要一个有用的软件功能集。我们将会把它们归类在核心模块下面。一个典型的核心模块层如图1.17所示。这里还有几个核心层一般都提供的模块的例子.

http://hi.csdn.net/attachment/201103/8/0_1299599705c92T.gif

图1.17 core system

  • 断言(Assertions). 断言是进行错误检查而插入的用来捕获逻辑错误以及违反程序员本意的代码。断言一般在最终产品生成时被移走。

  • 内存管理(Memory management). 目前所看到的所有游戏引擎都实现了它自己一套内存的分配机制,来确保高速的内存分配及释放以及减小内存碎片带来的负面影响(见5.2.1.4节)。

  • 数学库(Math library). 游戏是天生的对数学要求很高的。正因为如此,每个游戏引擎至少都有一个数学库,如果没有多个的话。这些数学库为向量及矩阵运算、四元数旋转、三角运算、对线、射线、圆、截头锥体(frusta)的几何操作等提供工具。插值(spline manipulation)、数值积分(numerical intergration)、系统方程式求解,以及所有程序员要求的其它功能。

  • 自定义数据结构及算法(Custom data structions and algorithms). 除非引擎设计人员决定完全的依赖第三方库如STL,那么一堆用来管理基本的数据结构(链表(linked lists)、动态数组(dynamic arrays), 二叉树(binary trees), hash maps, etc)及算法(搜索、排序等)的工作一般来说是需要的。它们一般是手动编码以求最小化或者消除掉动态分配,以及确保在目标平台上最佳的运行性能。

关于最常见核心模块的详细的讨论请看第二部分。

1.6.7 资源管理器(Resource Manager)

在每个引擎中以某种形式存在着,资源管理器提供一个统一的接口(或者几个接口)来存取任何及所有的游戏资源及其它引擎输入数据。有的引擎采用一个高度集中并且稳固的管理(如Unreal的packages,OGRE 3D的Resourcemanager类).其它的引擎则采用一些特别的方式,一般让游戏程序员直接存取磁盘上的原始文件或者从一个压缩结构中读取像Quake的PAK文件一样。一个典型的资源管理器如图1.18描述。

http://hi.csdn.net/attachment/201103/8/0_1299599712Mmr5.gif

图1.18 Resource Manager

1.6.8 渲染引擎(Rendering Engine)

渲染引擎是任何一个游戏引擎中最大和最复杂的组件之一。它可以有不同方式的架构,没有一个绝对的标准去做。不过就如同我们看到的一样,大多数现代的渲染引擎都采取了一些基本的设计哲学,并受到它们所依赖的3D显卡的设计很大的影响。

其中一种比较常见和有效的设计一个渲染引擎的方法是采取如下的层次架构:

1.6.8.1 低级渲染器(Low-Level Renderer)

低级渲染器,如图1.19所示,包括了所有的原始渲染引擎特性。在这个水平上,设计目标主要集中在如何快速且大量的渲染一堆几何图元,不考虑场景的哪个部分是可见的。这个组件可拆分为几个子组件,将在下面进行讨论。

http://hi.csdn.net/attachment/201103/8/0_1299599721hB4N.gif

图1.19 Low-Level rendering engine

  • 图形设备接口(Graphics Device Interface)

图形SDK,例如DirectX和OpenGL,需要一大堆合理的代码去查询可用的图形设备,初始化它们,设立渲染面(Render surface)(后台缓层(back-buffer),模板缓存(stencil buffer))等等。这些东西一般由我们称之为图形设备接口的组件管理(尽管每个引擎有它自己的术语)。

对一个PC游戏引擎,你还需要代码把你的渲染器跟Windows的消息循环结合起来。你可能会写一个"消息泵"(message pump),当Windows消息没有被处理的时候进行处理,否则就尽可能快的执行渲染循环。这个把游戏的按键输入与渲染器的屏幕输出循环连接在一起了。这个连接是不大好的,不过好处是可以把对硬件的依赖性最小化。后面我们会对这一问题作更深入的探讨。

  • 其它渲染组件

低级渲染器中的其它组件通力协作,目标在于收集提交的几何图元(geometric primitives)(有时候也叫做渲染包(render packets)),如网格(meshes), 线段系列(line lists), 点系列(point lists),粒子(particles), 地形块(terrain patches),文本字符串(text string),以及其它所有你想画的,然后尽可能的绘制它们。

低级渲染器一般提供一个视口(viewport),它由camera-to-world矩阵及3D透视的参数如FOV(field of view)及近剪裁面及远剪裁面得出。低级渲染器也根据它的材质系统(material system)以及动态光系统(dynamic lighting system)来管理图形硬件的状态及游戏的着色程序(shaders). 每个提交的图元都伴随着一个材质,并且被n盏动态光影响。材质(material)描述了当这个图元被渲染的时候,图元(primitive)所用到的贴图(texture),硬件需要事先被设定的状态,以及哪个顶点着色程序(vertex shader)/象素着色程序(pixel shader)被采用。光照和着色程序是一个非常繁杂的话题,在许多卓越的计算机图形学书籍中都有深入的探讨,包括[14]、[42]、[1]。

1.6.8.2 Scene Graph/Culling ptimizations

低级渲染器渲染所有的提交给它的几何图元,不管它是否可见(除了背面剔除(back-face culling)以及视锥剔除)。一般需要一个更高级的组件来闯荡江湖提交的图元数,根据某种方式的可见检测。这一层如图1.20所示。

对每个小的游戏世界,一个简单的视锥剔除(frustum cull)(去掉摄像机不可见的部分)是必要的。对于大的游戏世界来说,一个更高级的空间划分(spatial subdivision)数据结构可能用来提高渲染效果,它能对物体的潜在可见集(potentially visible set, PVS)进行快速的检测。PVS有多种形式,包括二叉空间分割树(binary space partitioning),四叉树(Quadtree),八叉树(octree), 多维检索树(kd-tree),或者sphere hierarchy. 空间划分有时候被称作scene graph, 尽管技术上来说后者只是一种数据结构且并不包括前者。Portals/occlusion culling可能也会应用到渲染引擎的这个层级中。

理想的,低级渲染器应该完全不知道上面所使用的空间划分或者scene graph。这个能让游戏团队重用它们的图元绘制系统,不过PSV系统则跟他们的游戏的特定的需求有关。OGRE 3D开源渲染引擎的设计是体现这一原理的极好的例子。OGRE提供了一个即插即用(plug and play)的scene graph架构工。游戏开发者可以从预定义实现的几个scene graph设计中挑选一个,或者提供一个自定义的实现。

1.6.8.3 视觉特效(Visual Effects)

现在的游戏引擎支持大量视觉特效,如图1.21所示,包括:

  • 粒子系统(particle system),用于烟,火、溅起来的水花等

  • 贴花(decal system),用于弹孔,脚印等

  • 光照贴图light mapping and 环境贴图environment mapping

  • 动态阴影dynamic shadows

  • 全屏后期特效full-screen post effect,作用在3D场景被渲染到离屏缓存上之后。

http://hi.csdn.net/attachment/201103/8/0_1299599728A73g.gif

图1.21 visual effects

一些full-screen post effects的例子:

  • 高动态光照渲染(high dynamic range(HDR) lighting and bloom.)

  • 全屏抗锯齿(full-screen anti-aliasing(FSAA))

  • 颜色纠正(color correction)以及各种滤镜(color-shift)特效,包括跳跃漂白(bleach bypass),过饱和(saturation),去饱和(de-saturation).

对一个游戏引擎来说,拥有一个特效系统来按理所有的粒子,贴花,还有其它特效的特殊渲染是常见的。粒子和贴花系统常常作为渲染引擎中一个比较独特的部件,并且作为低级渲染器的输入。另一个方面,光照贴图、环境贴图、阴影一般由渲染引擎内建管理。全屏后期特效则既可以作为渲染引擎内建的模块实现,也可以作为一个独立的模块来操作渲染器输出缓存。

1.6.8.4 前端(Front end)

大多数游戏都采用了一些2D的图形放在3D场景上面来实现各种目的,如:

  • heads-up display(HUD)

  • 游戏内建菜单或者控制台,或者其它开发工具,它们可能不会从最终产品中移除。

  • 可能有一个游戏内建的图形用户接口(GUI),允许玩家来改变他的角色的道具,配置战役中的战斗单位,或者完成其它复杂的任务。

这部分如图1.22所示。这些2D的图形一般是在一个正交投影下用绘制四边形(quads)(两个三角形)来实现的。或者是完全的3D制作的,采用四边形的公告板(bill-boarded)技术来使它们一直朝向镜头。

在这一层中可能还包含全动视频系统(full-motion video FMV system).这个系统负责播放预行录制的全屏的电影(游戏引擎渲染的或者其它渲染工具渲染的)

http://hi.csdn.net/attachment/201103/9/0_1299634542hJoz.gif

图1.22 front end

一个相关的系统是in-game cinematics(IGC).这个组件允许电影跟游戏本身结合起来。例如,当玩家走过一个城市,两个关健角色的对话就可能是一段in-game cinematic. IGCs可以包含或者不包含玩家控制的角色。它们可能被设计成当玩家失去控制权时出现,或者可能是巧妙的整合进游戏而玩家根本没有意识到这儿有一段IGC.

1.6.9 性能分析及调试工具(Profiling and Debugging Tools)

游戏是实时系统,因此,游戏引擎开发者一般需要查看分析他们的游戏的性能以作性能上的优化。另外,内存资源经常紧缺,所以开发者也很认真的对待和使用内存分析工具。如图1.23所示,性能查看和调试工具层,包含前面所提到的东西,另外还包括其它的调试工具,如调试用绘制(debug drawing),游戏内菜单或控制台(in-game menu/console),然后还有作为测试及调试用的记录及回放游戏的能力。

有许多好的通用的软件分析工具,如:

  • Intel’s VTune

  • IBM’s Quantify and Purify(part of the PurifyPlus tool suite)

  • Compuware’s Bounds Checker

不管怎样,大多数游戏引擎伴随着一套自定义的性能查看及调试工具。例如,它们可能包括下列其中一个或多个:

  • 一个手动分析代码的机制,以便计算某段特定代码的运行时间

  • 一个当游戏在运行时能够把分析数据显示在屏幕上的工具

  • 一个能把性能情况转存到文件文件或者Excel表格中的工具

  • 一个能检测多少内存被引擎使用,具体哪个子系统又用了多少的工具,并能以各种不同形式显示在屏幕上

  • 一个能在游戏结束或者运行中把内存使用情况,峰值,及泄漏情况转存的机制

  • 能通过代码改变调试输出状态,打开/关闭调试输出种类及控制输出详细程度的工具

  • 记录游戏事件并回放的机制。这个比较难做好,不过做得恰当的话将会是一个很有价值的追踪bug的工具

1.6.10 碰撞及物理

碰撞检测对每个游戏来说都是很重要的。没有它,物体之间就会相互渗透,不可能跟虚拟的3D世界进行任何合理的交互。有的游戏还包含了一个真实世界的或者接近真实世界的动态模拟。在游戏业中我们称之为“物理系统”,不过“刚体物理”(rigid body dynamics)这个概念更准确,因为我们一般只考虑刚体的动作(运动学上的)及引起这个动作的力和扭矩(力学上的)。这一层如图1.24所描述。

碰撞和物理经常非常紧密的成对出现。这是由于碰撞的被检测,往往是物理上受力约束及综合逻辑的结果。今天很少有游戏公司写他们自己的碰撞/物理引擎,代之以将第三方的SDK整合进引擎。

  • Havok. 今天业界的黄金标准。非常丰富的特性及全面的优异的性能

  • PhysX. NVIDIA的。这是另外一个卓越的碰撞及物理引擎。它被整合进Unreal Engine 3,还是PC游戏开发的一个独立的免费产品。PhysX本来是设计为Ageia的新的物理加速芯片的接口的。SDK现在被NVIDIA所有并发布,他们修改PhysX让它跑在了公司的最新的GPU上。

http://hi.csdn.net/attachment/201103/10/0_1299765625KXXx.gif

图1.24 Collision and physics subsystem

也有开源的物理/碰撞引擎。可能最为有名的是Open Dynamics Engine(ODE). 更多信息请参见: .

I-Collide, V-Collide, 还有RAPID是另外的有名的非商业碰撞检测引擎。这三个都是由University of North Caolina(UNC)开发的。更多信息请参见:http://www.cs.unc.edu/~geom/I_COLLIDE/index.html, , .

1.6.11 动画(Animation)

任何有有生命的或者类似有生命的角色的游戏(人类、动物、卡通角色,甚至机器人),都需要一个动画系统。游戏中用到的动画系统有五种:

  • 精灵/图片动画(sprite/texture animation)

  • 刚体层级动画(gigid body hierarchy animation)

  • 骨骼动画(skeletal animation)

  • 顶点动画(vertex animation)

  • 形态目标(morph targets, MT)

骨骼动画允许一个细致的3D角色模型的网格能被一个由动画师用一个有关联的非常简单的骨骼定位。当骨骼移动,这些3D模型网格上的顶点也随之移动。尽管有些引擎中使用MT及顶点动画,骨骼动画是今天的游戏中最流行的动画制作方式。因为,它将作为本书的重点。

你可能注意到图1.11中,骨骼网络渲染(Skeletal Mesh Rendering)是分开的渲染器跟动画系统之间的桥梁。这儿有一个非常紧密的协作,不过接口是良好定义了的。动画系统为骨骼中的每一根骨头计算出一个位置,然后将位置作为矩阵系列(palette of matrices)之一传递给渲染引擎。渲染器对每个顶点用矩阵系统中的一个或多个矩阵进行坐标变换,作出一个最终的混合的顶点位置。这个过程被称之为蒙皮(skinning)。

动画和物理系统之间也有一个紧密的关系, 比如当使用布娃娃(rag doll)的时候。布娃娃是一个柔软的(一般是没有生命的)动画角色,它的身体的动画由物理系统模拟。物理引擎将它的身体的各个部件看作是一个有限定关系的刚体,然后算出它们的位置及朝向。动画系统计算出渲染引擎需要用来将角色绘制到屏幕上去的矩阵系列.

1.6.12 人机设备接口(Human Interface Devices(HID))

任何一个游戏都需要处理玩家的输入,它们由以下各种HID获得:

  • 键盘及鼠标

  • 游戏手柄

  • 其它特殊的游戏控制器,如方向盘, 钓鱼杆,跳舞毯, Wii遥控器,等等。

有时候我们称这个部件为用户I/O组件,因为我们也通过HID给玩家以输出,如游戏手柄的力反馈/震动,或者Wii遥控器发出来的声音。

HID引擎组件有时候架构成将某个流行的硬件平台上的底层游戏控制跟上层游戏控制分离开来。它转发硬件传来的原始数据,为游戏手柄的每个摇杆中间划出一个不活动区域,检测按钮按下和松开事件,双击按钮事件,突发的和平缓的加速输入(如PS3的sixaxis手柄),等。它一般提供一个可以自定义物理输入和游戏功能映射的机制。它还经常包含一个检测"合弦"输入(多个按键一起按下),序列输入(在某个限定时间内以一定次序按键),和手势(对按键、摇杆、加速器的序列输入).

在任何游戏引擎中,声音是跟图象一样重要的。不幸的是,声音经常不如画面渲染、物理、动画、人工智能及游戏性那么受重视。一个佐证便是: 程序员经常在写代码的时候把扬声器关掉!(事实上,我知道有许多甚至没有扬声器或者耳机的游戏程序员)。但是,离开优秀声音引擎,没有哪个伟大的游戏能完成。音乐层如图1.27所描述。

声音引擎变化多样。Quake和Unreal的声音引擎都非常基础,游戏开发团队经常通过自定义的功能或者用私有的(in-house)解决方案取代它来增加声音引擎。对于DirectX平台(PC和Xbox 360),微软提供一个叫做XACT的卓越的声音工具集。EA开发了一个先进、强劲的叫做SoundR!OT的声音引擎。与第一方工作室有关的如Naughty Dog, Sony Computer Entertainment America(SCEA)提供一个叫做Stream的强大的3D声音引擎,它已经用在大量PS3的游戏如Naughty Dog的Uncharted: Drake’s Fortune。不过,即使游戏开发团队使用一个已有的声音引擎,每个游戏仍需要大量的定制的软件开发、整合、调整,以及细节上的东西,以便在最终产品中有一个高质量的音效。

1.6.14 多人在线/网络(Online Multiplayer/Networking)

许多游戏允许在一个虚拟世界中有多个玩家游戏。多人游戏至少有四种风格:

  • 单屏多人(Single-screen multiplayer). 两个或多个人机接口设备(HID)(手柄, 键盘, 鼠标等)连接到唯一一台街机(arcade machine)、PC或者家用机(console)上。多个玩家共存在一个虚拟世界中,一个唯一的摄像机同时让所有的玩家在画面上。这种类型的游戏包括: Smash Brothers, Lego Star Wars, Gauntlet.

  • 分屏多人(Split-screen multiplayer). 多个玩家共存于一个虚拟世界,多个HID连接到一台游戏机,不过每个人都有自己的摄像机,屏幕也被分成多个区块以让所有的玩家都可以看到自己的角色。

  • 多人联网(Networked multiplayer). 多台计算机或者家用机通过网络连接在一起,每台机器是其中某个玩家的主机。

  • 大型多人在线游戏(Massively multiplayer online games MMOG).就如字面意思所示,成百上千的玩家,可以同时在一个巨大的、稳定的、在线的由一个强大的中央服务器作为主机的虚拟世界中游戏。多人游戏网络层如图1.28所示。

多人游戏跟他们的单人版本在许多地方有相似之处。不过,要支持多人游戏,在游戏引擎模块设计上都会造成一个很大的影响。。游戏世界对象模型,渲染器,HID,控制机制,动画机制都会完全受影响。把多人游戏的特性添加到一个已有的单人游戏引擎基本上不是完全不可行,尽管它是一个让人望而却步的任务。尽管如此,许多游戏团队成功的做到了。那说明,如果你能接受那么奢侈的话,最好是从开发的第一天就开始把多人特性考虑进去。

这个是非常有意思的,如果是从另外一个方向的话 - 把一个多人游戏变为一个单人的 - 是一件非常简单的事。事实上,许多游戏引擎把单人游戏模式视为多人游戏的一个特例,这种情况刚好只有一个玩家。Quake引擎由于它的client-on-top-of-server模式而闻名:一个唯一的可执行程序,运行在一台PC上,在单人作战模式中即扮演客户端又扮演服务器。

1.6.15 游戏可玩性基础系统(Gameplay Foundation System)

“游戏可玩性”(gameplay)这个术语涉及到游戏中的事件的发生,管理游戏所在的虚拟世界的规则,玩家控制角色的能力(即player mechanics)及世界中其他角色和物件的能力,及玩家的目标。游戏可玩性可以用实现引擎其它部分的同样的语言来实现,或者用一个高级脚本语言来实现,有时候两者皆用。作为连接游戏可玩性代码及我们之前讨论了很多的低级引擎模块的桥梁,多数游戏引擎引入一个我称之为gameplay foundation的层(因为没有一个标准的名字).如图1.29所示,这一层提供了一套核心的工具,游戏逻辑在它之上可以很便的实现。

http://hi.csdn.net/attachment/201103/13/0_1300008208c0su.gif

图1.29 gameplay foundation layer

1.6.15.1 游戏世界及物件原型(Game Worlds and Object Models)

游戏可玩性基础层引入了游戏世界的概念,包括静态和动态的元素。世界的内容一般用一个面向对象的方式作为原型(一般,但并不一定,使用一个面向对象的编程语言). 在本书中,组成游戏的物件类型集合叫作游戏物件原型(game obejct model).游戏物件原型为游戏中的不同种类的物体提供了一个实时的模拟。

典型的游戏物件包括:

  • 静态的背景几何图形,如建筑物、路、地形(往往是某一特定类型)等

  • 动态刚体,如石头、汽水瓶、椅子等

  • 玩家控制的角色(PC)

  • 非玩家控制的角色(non-player characters, NPC)

  • 武器

  • 投射物

  • 车辆

  • 灯光(可能出现在运行时的动态场景中,或者仅仅用于离线的静态光照)

  • 摄像机

  • 等等

游戏世界原型很紧密的依赖于软件对象模型(software object model),这种模型可以遍布于整个游戏引擎。软件对象模型涉及到用来实现面向对象软件的语言的特性、政策及方便性。在游戏引擎的情况中,软件对象模型回答以下问题:

  • 你的游戏引擎是用面向对象的方式设计的吗?

  • 你会使用哪种语言?C? C++? Java? OCaml?

  • 这些类的关系将如何组织?一个巨大的紧密集成的层次关系,还是一些松散的联结的模块?

  • 你会使用模板和policy-base的设计吗?或者传统的多态?

  • 对象怎么被引用?直接的指针?智能指针?句柄?

  • 对象怎么被唯一的识别?内存中的地址?名字?全局唯一的标识号?(Golobal Unique Identifier, GUID).

  • 游戏物件的生命周期如何管理?

  • 游戏物件的状态如何随着时间模拟?

我们将对软件对象模型和游戏物件原型在14.2节进行深入讨论。

1.6.15.2 事件系统(Event System)

游戏物件总是需要跟其它的物件交流。这个可以有多种方式来实现。比如,发送消息的物件可以简单的调用收消息的物件的成员函数。在一个事件驱动(Event-driven)机制下,就像一个典型的图形用户接口一样,也是一种常见的内部物体交互的机制。在事件驱动机制下,发送者创建一个小小的称之为事件(Event)或者消息(message)的数据结构,包含有消息的类型或者其它被发送的任何参数。这个事件通过调用它的事件处理机制(event handler function)传递给接收者。事件也可以存在一个队列中以便将来某个时刻处理。

1.6.15.3 脚本系统(Scripting System)

许多游戏引擎采用脚本语言以更加方便和快速的开发游戏特定的可玩性的规则和内容。没有脚本语言的话,每次对引擎中的逻辑或者数据结构的改动,你必须重新编译和链接你的游戏可执行程序。但当整合了一个脚本语言到引擎中的话,对游戏逻辑和数据的改动只需要修改和重新读取脚本代码就可以了。有的引擎还可以让游戏运行时重新读取脚本。有的引擎则需要在重新链接接脚本之前停止游戏。不管哪种情况,这个都比重新编译链接游戏可执行程序要快很多。

1.6.15.4 人工智能基础模块(Artificial Intelligence Foundations)

传统上,AI处在游戏软件的边缘 - 本质上并不认为它是游戏引擎的一部分。不过最近,游戏公司认可了在几乎每个AI系统中都存在的模块的出现,这个基础模块慢慢的被严格的认为是游戏引擎的一部分。

一个叫做Kynogon的公司开发了一个叫做Kynapse的商业AI引擎,在作为"AI基础模块"的它上面开发游戏AI逻辑可以更加容易。Kynapse提供一个非常强大的特性集,包括:

  • 一个路径节点及漫游区域的网络,它们定义了人工智能角色可以自由移动而不必担心撞到世界地形的区域或者路径。

  • 每个自由漫游的区域的简单的碰撞信息

  • 某个区域的入口及出口的知识,以及在每个区域的哪个位置敌人可以看到或者偷袭你.

  • 基于A*算法的寻路引擎

  • 挂到碰撞机制和世界原型中,作视线追踪(line of sight traces)和其它感觉。

  • 定制的世界物件原型,可以告诉AI感兴趣的所有的实体(同盟、敌人、障碍),允许动态的避开移动的物体,等等

Kynapse也提供一个AI描述层,包括大脑(brain)的概念(每个角色一个),代理(每个负责处理一个特殊的任务,如从一个点移动到另外一个点,向敌人开火,寻找敌人,等等),和动作(负责处理角色表现一个基本的行动,结果一般是在角色的骨骼系统上播放一个动画).

1.6.16 游戏特定子系统(Game-Specific Subsystems)

在游戏可玩性基础层和其它低层引擎组件之上,游戏可玩性程序员和策划们通力协作来实现游戏本身。游戏可玩性系统一般是数目众多、变化也多,并且根据开发的游戏而定制的。如图1.30所示,这些系统包括但不限于玩家控制的角色的结构,游戏中的摄像机系统,NPC的AI,武器系统,车辆,等等。如果说引擎和游戏之间有一条明显的分界线的话,那么就是游戏特定子系统跟游戏可玩性基础系统。事实上,这条线不可能真的那么明确。至少有的游戏定制子系统会渗透到游戏可玩性基础系统中,甚至引擎内核之中。

http://hi.csdn.net/attachment/201103/14/0_13001101160W40.gif

图1.30 Game-specific Subsystem