一个游戏引擎一般是由工具套件和一个运行时组件组成。
目标硬件
目标硬件层,是将运行游戏的电脑系统或者主机。
设备驱动程序
硬件驱动是比较底层的由操作系统或者硬件开发商提供的软件组件。硬件驱动管理硬件资源,把操作系统与引擎上层跟无数不同的可用的硬件细节操作隔离开来。
操作系统
在PC上,操作系统是一直运行着的。它指挥着多个程序在一台电脑上运行,其中就包括你的游戏。这意味着PC游戏不能假设拥有硬件的所有控制权。
在游戏主机上,操作系统通常只是一个轻量级的库,链接到游戏的执行档里。在游戏主机上,游戏一般完整的“拥有”整个硬件。
第三方SDK和中间件
大多数游戏引擎都使用了许多第三方的SDK和中间件,SDK提供基于函数或者基于类的接口一般称之为应用程序接口(API).
数据结构和算法
STL. C++标准模板库提供了大量的代码和算法来处理数据,字符串和I/O流
STLport. 这是一个轻量级的简化过的STL的实现版本
Boost. Boost是一个强大的处理数据结构和算法的库,被设计成STL的风格。(在线的Boost文档还是一个学习计算机科学的好地方。)
Loki. Loki是一个强大到让你头痛的通用编程模板库。
STL在PC上面使用是没有问题的,因为它的高级的虚拟内存机制对于小心的内存分配不是那么严格(但仍然需要小心)。在主机上,由于受限的或者根本就没有虚拟内存机制,还有昂贵的cache miss开销,你最好自己写一个具有可预测的或者极少内存分配的自定义数据结构(在PC项目上这样做的话也不会错到哪去).
关于STL标准在游戏应用的问题和解决方案参考:http://www.open-std.org/jtcl/sc22/wg21/docs/papers/2007/n2271.html
图形
Glide. 这是一个给老式Voodoo显卡的3D图形SDK. 它在硬件坐标转换和光照加速(hardware T&L)出现的时代非常流行。
OpenGL. 一个广泛使用的轻便的3D图形SDK.
DirectX. 微软的3D图形SDK,OpenGL的主要竞争对手。
libgcm是一个底层的直接面向PS3的RSX显卡的接口,是索尼提供的一个比OpenGL更高效的选择。
Edge是一个由Naughty Dog还有索尼为PS3提供的强大的渲染和动画引擎,它被许多第一方及第三方游戏工作室采用。
碰撞和物理
碰撞检测及刚体物理(在游戏开发交流中简称为“物理”)由下面这些有名的SDK提供支持:
* Havok. 一个非常流行的工业水准的物理及碰撞引擎
* Phy X. 另外一个具有工具水准的物理及碰撞引擎,可以从NVIDIA那免费下载。
* Open Dynamic Engine.(ODE) 是一个非常流行的开源物理/碰撞模块。
角色动画
部分商业的动画包:
* 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在欧洲的高级技术团队开发了一个强劲的高效的动画引擎,还有一个为了渲染的高效的几何处理引擎。
人工智能(artificial interlligence, AI)
* Kynapse. 一直到最近,人工智能一直是由每个游戏自定义的。不过,有家叫Kynogon的公司制作了一个中间层的SDK叫作Kynapse.这个SDK提供低级的AI模块,包括寻路,绕开静态和动态的物体,发现某块区域内的弱点(例如,某个开着的窗户可能就是埋伏的好地方),还有一个合理的关于AI及动画的接口。
生物的角色模型(Biomechanical Character Models)
* Endorphin and Euphoria. 这些是用真实人类移动的高级生物模型制作的角色动画包。
平台独立层
大多数游戏引擎需要运行在不同的平台上,绝大多数游戏引擎架构上都有一个平台无关层。这一层建立在硬件层、驱动层、操作系统,还有其它第三方软件上之,把引擎的剩余部分和大部分的底层平台细节隔离开来。
他包装了常用的C标准库,操作系统调用,以及其它的基础的API,保证引擎在所有不同的硬件平台上的行为一致性。
核心系统
* 断言(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)及算法(搜索、排序等)的工作一般来说是需要的。它们一般是手动编码以求最小化或者消除掉动态分配,以及确保在目标平台上最佳的运行性能。
资源管理
每个引擎都有某种形式的资源管理器,它提供一个统一的接口(或者几个接口)来存取任何及所有的游戏资源及其它引擎输入数据。
渲染引擎(Rendering Engine)
渲染引擎是任何一个游戏引擎中最大和最复杂的组件之一。它通常采用分层结构:
低级渲染引擎
包括了所有的原始渲染引擎特性。它的设计目标主要集中在高速渲染大量几何图元,不考虑场景的哪个部分是可见的。
图形设备接口(Graphics Device Interface)
图形SDK负责:查询可用的图形设备,初始化它们,设立渲染面(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)被采用。
场景图/剔除优化(Scene Graph/Culling ptimizations)
低级渲染器渲染所有的提交给它的几何图元,不考虑图形是否确实可见。一般需要一个更高级的组件,才能基于某些可视性判别算法去限制提交的图元数量。
对每个小的游戏世界,一个简单的视锥剔除(frustum cull)(去掉摄像机不可见的部分)是必要的。对于大的游戏世界来说,一个更高级的空间划分(spatial subdivision)数据结构可能用来提高渲染效果,它能对物体的潜在可见集(potentially visible set, PVS)进行快速的检测。PVS有多种形式,包括二叉空间分割树(binary space partitioning),四叉树(Quadtree),八叉树(octree), 多维检索树(kd-tree),或者sphere hierarchy。Portals/occlusion culling等方法可能也会应用到渲染引擎的这个层级中。
视觉效果(Visual Effects)
包括:
粒子系统(particle system),用于烟,火、溅起来的水花等
贴花(decal system),用于弹孔,脚印等
光照贴图light mapping and 环境贴图environment mapping
动态阴影dynamic shadows
全屏后期特效full-screen post effect,作用在3D场景被渲染到离屏缓存上之后。
一些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).
前端(Front end)
大多数游戏都采用了一些2D的图形放在3D场景上面来实现各种目的,如:
heads-up display(HUD)
游戏内建菜单或者控制台,或者其它开发工具,它们可能不会从最终产品中移除。
剖析及调试工具(Profiling and Debugging Tools)
游戏是实时系统,因此,游戏引擎开发者需要经常剖析游戏性能,一便优化。另外,内存资源经常紧缺,开发者也要大量使用内存分析工具。
有许多好的通用的软件分析工具,如:
Intel's VTune
IBM's Quantify and Purify(part of the PurifyPlus tool suite)
Compuware's Bounds Checker
大多数游戏引擎也加入一套自定义的性能查看及调试工具。它可能包含这些功能:
手工插入测量代码,为某些代码计时
游戏运行期间,在屏幕上显示性能统计数据
把性能情况转存到文件文件或者Excel表格中的工具
计算引擎和子系统所耗内存,并显示到屏幕上
在游戏结束或者运行中把内存使用情况,峰值,及泄漏情况统计输出
能在代码改变调试输出状态,开关调试输出种类并设置输出的冗长级别
记录游戏事件并回放的机制
碰撞及物理
碰撞检测对每个游戏来说都是很重要的。没有它,物体之间就会相互渗透,不可能跟虚拟的3D世界进行任何合理的交互。有的游戏包含真实或半真实的动力学模拟。这在游戏业中称为“物理系统”,更正确的术语是刚体动力学模拟,因为游戏中通常只考虑刚体的运动(运动学)及产生运动的力和力矩(动力学)。
第三方的物理SDK:
Havok. 今天业界的黄金标准。非常丰富的特性及全面的优异的性能
PhysX. NVIDIA的。这是另外一个卓越的碰撞及物理引擎。它被整合进Unreal Engine 3,还是PC游戏开发的一个独立的免费产品。PhysX本来是设计为Ageia的新的物理加速芯片的接口的。SDK现在被NVIDIA所有并发布,他们修改PhysX让它跑在了公司的最新的GPU上
动画(Animation)
游戏中5中基本动画:
精灵/图片动画(sprite/texture animation)
刚体层级动画(gigid body hierarchy animation)
骨骼动画(skeletal animation)
顶点动画(vertex animation)
形态目标(morph targets, MT)
骨骼动画让动画师使用相对简单的骨头系统去设定精细三维角色网格的姿势。
骨骼网络渲染(Skeletal Mesh Rendering)组件是连接的渲染器跟动画系统的桥梁。动画系统为骨骼中的每一根骨头计算出一个位置,然后将位置作为矩阵系列(palette of matrices)之一传递给渲染引擎。渲染器对每个顶点用矩阵系统中的一个或多个矩阵进行坐标变换,作出一个最终的混合的顶点位置。这个过程被称之为蒙皮(skinning)。
人机设备接口(Human Interface Devices(HID))
游戏输入:
* 键盘及鼠标
* 游戏手柄
* 其它特殊的游戏控制器,如方向盘, 钓鱼杆,跳舞毯, Wii遥控器,等等。
音频
多人在线/网络(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).就如字面意思所示,成百上千的玩家,可以同时在一个巨大的、稳定的、在线的由一个强大的中央服务器作为主机的虚拟世界中游戏。
多人游戏跟他们的单人版本在许多地方有相似之处。但是,支持多人游戏,会深切影响某几个游戏引擎组件的设计。单人引擎改成多人引擎很困难,但是多人引擎改成单人引擎很简单。
游戏性基础系统(Gameplay Foundation System)
"游戏性"(gameplay)指游戏内进行的活动、支配游戏虚拟世界的规则、玩家角色的能力、其他角色和对象的能力、玩家的长短期目标。
游戏世界和游戏对象模型
典型的游戏物件包括:
静态的背景几何图形,如建筑物、路、地形(往往是某一特定类型)等
动态刚体,如石头、汽水瓶、椅子等
玩家控制的角色(PC)
非玩家控制的角色(non-player characters, NPC)
武器
投射物
车辆
灯光(可能出现在运行时的动态场景中,或者仅仅用于离线的静态光照)
摄像机
关注这些问题:
你的游戏引擎是用面向对象的方式设计的吗?
你会使用哪种语言?C? C++? Java? OCaml?
这些类的关系将如何组织?一个巨大的紧密集成的层次关系,还是一些松散的联结的模块?
你会使用模板和policy-base的设计吗?或者传统的多态?
对象怎么被引用?直接的指针?智能指针?句柄?
对象怎么被唯一的识别?内存中的地址?名字?全局唯一的标识号?(Golobal Unique Identifier, GUID).
游戏物件的生命周期如何管理?
游戏物件的状态如何随着时间模拟?
事件系统(Event System)
游戏对象需要和其他对象通信。
脚本系统(Scripting System)
许多游戏引擎采用脚本语言以更加方便和快速的开发游戏特定的可玩性的规则和内容。没有脚本语言的话,每次对引擎中的逻辑或者数据结构的改动,你必须重新编译和链接你的游戏可执行程序。但当整合了一个脚本语言到引擎中的话,对游戏逻辑和数据的改动只需要修改和重新读取脚本代码就可以了。有的引擎还可以让游戏运行时重新读取脚本。有的引擎则需要在重新链接接脚本之前停止游戏。不管哪种情况,这个都比重新编译链接游戏可执行程序要快很多。
人工智能基础模块(Artificial Intelligence Foundations)
一般的AI一直是为个别游戏专门开发的软件,不隶属于游戏引擎,但最近游戏开发商找到每个AI系统的共有模式,是它的基础部分渐渐进入游戏引擎的范畴。
个别游戏专用子系统(Game-Specific Subsystems)
在游戏性基础层和其它低层引擎组件之上,游戏程序员和设计师合作实现游戏本身的特性。游戏性系统通常变化很大,并且根据开发的游戏而定制的。
工具及资产管道
游戏引擎需要读取大量数据,数据形式包括游戏资产、配置文件、脚本等。图1.31描述了现代游戏引擎中用到的一些类型的数据。粗黑箭头展示了数据是如何从创建它们的最原始的工具转换到最终的游戏引擎中去的。细灰箭头则表示了表示了这些各种各样的资源如何关联或者引用其它资源的。
数字内容创建工具
游戏本质上就是多媒体应用。游戏引擎的输入数据形式广泛。所有这些源数据都需要由艺术家(artists)使用数字内容创作(digital content creation DCC)应用软件制作。
资产调节管道
DCC程序所使用的数据格式极少有适合拿来直接在游戏中使用的。主要原因有两个:
DCC程序中模型在内存中的数据往往比游戏所需要的复杂得多。
DCC程序的文件格式往往读取速度太慢,并且有的还是一个封闭的私有的格式。
因此,DCC程序创建的数据一般导出为一个更标准的格式,或者用一个自定义的格式用于游戏。
数据从DCC程序中导出之后,有时必须再处理,才能在游戏引擎中使用。从DCC到游戏引擎的管道称资产调节管道。每个游戏引擎都有某种形式上的资产调节管道。
3D模型/网格数据
在游戏中常见的几何体一般由两种类型的数据构成。
笔刷几何图形(Brush Geometry)
笔刷几何图形是用一些凸包(convex hulls)集合定义的,每个凸包由多个平面定义。笔刷一般由游戏世界编辑器创建和编辑。
优点:
* 快速且易于创建
* 游戏策划能存取 - 经常用来设计用作游戏原型的关卡
* 能作为碰撞数据和渲染数据使用
缺点:
* 低精度 - 难以创建复杂形体
* 不支持有关节的物体或者动画角色
3D模型(网格Mesh)
对细致场景元素,3D模型(也被称为网格)优于笔刷几何图形。网格是由三角形和顶点组成的复杂的图形(网格也可能由四边形或者其它可再分的几何面(surface)构成。
骨骼动画数据
骨骼网格(skeletal mesh)是一种特殊的网格,为关节动画而绑定到骨骼层次结构之上。
游戏引擎需要3种数据去渲染骨骼网格。
网格本身
骨骼层次结构(skeletal hierarchy)(关节名称,父子节点关系还有这个节点绑定到网格时的原始姿势)
一个或多个动画片断(animation clips),用来指明随着时间关节是如何运动的
音频数据(Audio Data)
音频片断一般是由Sound Forge或者其它音频创作工具导出的,有不同的格式和采样率。音频文件通常组织成音频库,以方便管理、容易载入及串流。
粒子系统数据(Particle Systems Data)
现代游戏使用非常复杂的粒子特效。粒子效果由视觉特效的专门设计师制作。许多游戏引擎有自制的的粒子效果编辑工具,只提供引擎支持的效果。
游戏世界数据和世界编辑器(Game World Data and the World Editor)
许多Radiant游戏引擎的变体被用于大多数游戏引擎,它基于Quake技术
半条命2(Half-Life 2)引擎提供一个叫做Hammer的世界编辑器
UnrealEd是UnrealEngine的世界编辑器。这个强大的工具还可以管理所有能被引擎接受的数据类型的数据。
一些构建工具的方法(Some Approaches to Tool Architecture)
游戏引擎工具集(tool suite)可能以很多种方式来架构。