第 7 章
通用模拟的胎动
当凯斯梅特的节点被连接起来、编辑器内运行按钮被按下、游戏逻辑即时生效的那一刻,一条从程序员到美术师的权力转移通道已经打开——这条通道一旦打开,就再也无法关闭,但引擎架构为此付出的运行时开销与跨平台兼容性代价,将在下一代主机战争中成为新的压力点。然而,就在工具链的权力格局重新洗牌的同时,另一场更隐蔽的运动正在游戏引擎产业的边缘地带展开。它的参与者不是游戏开发者,它的驱动力不是更好的画面或更快的迭代,它的核心问题甚至与游戏无关。
把时间拨回到2003年,一批来自建筑、军事和工业软件领域的人,几乎同时开始做一件在当时看来相当奇怪的事:他们试图用游戏引擎做游戏之外的事。北京一家建筑可视化公司的技术团队在2003年底接到了一个项目:为一处尚未动工的高档住宅小区制作虚拟漫游系统。客户的要求很明确——购房者应该能够在销售中心的电脑上自由走动,查看不同户型的采光条件,感受从客厅窗户望出去的景观视野。团队评估了当时可用的几种技术方案。
专门的建筑可视化软件如3ds Max和Lightscape可以生成照片级静态渲染图,但无法实时交互。基于QuickTime VR的全景节点方案支持有限的角度切换,但无法实现连续的空间漫游。虚拟现实平台如Vega Prime功能强大,但单套授权费用高达数万美元,且需要专业的图形工作站。
技术总监在一次内部讨论中提出了一个替代方案:使用虚幻引擎2.5。这款引擎在游戏行业已经证明了其实时渲染能力,授权费用相对可承受,而且埃匹克公司提供了源码访问权限。团队用三周时间完成了初步搭建。他们从建筑模型导入几何体,在引擎编辑器中布置材质和光照,编写了简单的摄像机控制脚本。效果令人振奋——实时光影让大理石地面反射出柔和高光,动态天空盒让不同楼层的景观视野随时间和天气变化。
然后测试人员走了起来,直接穿过了墙壁。问题不在代码里。虚幻引擎的碰撞检测系统根植于一套关于世界如何运作的深层假设。
在引擎的默认配置中,场景几何体被分类为“世界几何”——这个分类在游戏逻辑中意味着特定行为:它可以被特定武器破坏,可以被载具撞击移动,可以在爆炸中产生碎片。要让一堵墙变得不可穿越,开发者需要配置碰撞通道、设置物理材质属性、定义阻挡体积、关闭可破坏标记。这些参数分布在至少四个不同的属性面板中,部分设置隐藏在脚本层的默认值里,另一些与伤害系统和粒子特效系统存在耦合。
建筑可视化团队不需要武器系统、伤害模型、可破坏物标记、爆炸粒子特效。他们只需要一堵在虚拟空间中阻止 avatar 穿过的几何边界。但引擎的架构不允许他们简单地声明这个需求。他们必须反向操作——在配置文件中逐项关闭那些为游戏设计的子系统,然后为每一面墙手动添加不可穿越的碰撞体。
整个调试过程持续了将近两周。这个看似微小的配置问题暴露了一个被整个产业忽视的事实:游戏引擎不是中性的模拟平台。
它的每一层架构都携带着关于世界的隐含假设——碰撞检测不只是碰撞检测,它是“玩家角色–敌方单位–可破坏掩体–爆炸范围”这套游戏逻辑的物理化身。渲染管线不只是渲染管线,它的默认优化参数假设视点高度在一米七左右——一个站立持枪的士兵的眼睛位置,而不是一个坐在轮椅上的购房者的视线高度。帧循环的时间步长被调校为适合每秒三十帧的动作响应节奏,而不是建筑漫游中缓慢平滑的摄像机推移。
当这家公司的技术总监最终完成配置时,他做了这样一件事:将所有修改过的参数整理成一份文档,附在项目交付文件之后。这份文档记录的不是代码修改,而是一系列“剥离”——剥离武器系统、剥离伤害模型、剥离可破坏物标记、剥离AI感知系统、剥离玩家状态机。每一项剥离都对应着一个被关闭的游戏功能。而每一个被关闭的游戏功能,都对应着引擎源代码中一个被硬编码的游戏假设。
这份文档从未公开发表。但它在小范围内被传阅,成为建筑可视化圈子里的一个参考。
读到这份文档的人会意识到同一个事实:他们做的不是用游戏引擎做建筑可视化,而是把游戏引擎中不是建筑可视化的部分剥离掉。这两件事听起来相似,本质上截然相反。
早在2001年,埃匹克公司内部就已经有人注意到了这个现象。虚幻引擎2.0发布后,授权客户名单上开始出现一些不属于游戏行业的名字。一家美国建筑事务所购买了授权,用于向客户展示未建成的办公楼方案。一家博物馆委托开发商用虚幻引擎构建古罗马广场的虚拟复原。
最引人注目的是一支通过承包商接触引擎源代码的美国陆军研究团队——他们询问是否可以将弹道模型集成到渲染管线中。这些需求在当时被视为边缘案例。埃匹克的销售团队没有为这类客户准备专门的技术支持方案。授权协议中的条款仍然以“游戏产品”为默认前提,对非游戏用途的权利义务界定模糊。但蒂姆·斯威尼在一次内部技术讨论中提出了一个观点。
这个观点的记录保留在后来GDC演讲的早期草稿文件中:如果一套软件能够实时渲染三维世界、处理物理碰撞、管理交互逻辑,那么它的能力边界应该由输入数据和交互规则定义,而不是由“游戏”这个品类定义。这个判断在当时听起来像是哲学思辨。2001年的游戏引擎产业正忙于争夺PlayStation 2和Xbox的开发合同。没有人有精力思考引擎的非游戏应用这种话题。
但斯威尼的直觉来自他对引擎架构的长期观察。虚幻引擎的核心循环——输入采集、状态更新、物理模拟、可见性计算、光照计算、渲染提交——在抽象层面上并不依赖于“玩家”“敌人”“得分”这些游戏概念。它依赖的是更底层的抽象:一个带有变换矩阵的场景节点,一组带有物理属性的碰撞体,一套响应输入事件的状态机。理论上,你可以把玩家替换成参观者,把敌人替换成展品,把得分替换成浏览时长。引擎不关心这些标签。
但理论上和工程上之间的距离,正是那家建筑可视化公司用将近两周时间才填平的鸿沟。
斯威尼看到了这个鸿沟的存在,但在2001年,他还没有找到跨越它的技术方案。同一时期,在距离埃匹克北卡罗来纳总部数千公里之外的加州,另一群人正在从完全不同的方向逼近同一个问题。美国海军研究办公室资助了一个城市战训练系统的研发项目,研究团队选择了id Tech引擎作为基础平台。选择理由很直接:卡马克的渲染器在处理大量动态光源方面效率极高,而城市战环境中的爆炸、火焰和探照灯需要精确的实时光照计算。
但研究团队很快发现,id Tech引擎的架构假设与军事训练需求之间存在一系列根本性的不匹配。
第一个不匹配出在输入设备上。id Tech引擎的输入系统被硬编码为处理键盘、鼠标和标准游戏手柄的信号——Win32消息循环捕获按键事件,DirectInput接口读取鼠标位移和手柄摇杆状态。军事训练系统需要接入的是一套完全不同的外设:带有位置追踪传感器的武器模拟器、支持多点触控的战术地图桌、环绕投影系统需要的多通道视口同步信号。
研究团队的工程师不得不深入引擎的输入处理层。他们在Win32消息循环和DirectInput调用之间插入了一个抽象层,将自定义硬件的信号转换成引擎能理解的按键和鼠标移动事件。一把带有位置追踪的M4卡宾枪模拟器发出的六自由度姿态数据,被映射成鼠标移动和键盘方向键的组合信号。战术地图桌上的多点触控手势被转换成一系列快捷键宏。环绕投影的多通道同步信号则需要修改渲染管线的视口分割逻辑。
这是一次外科手术式的修改。每一处切口都在揭示同一个事实:引擎的输入架构从设计之初就假设用户坐在显示器前,双手放在键盘和鼠标上,单人操作,单一视点。这个假设不是缺陷——对于游戏来说,它是合理的优化。但对于任何需要非标准输入设备或多人协同操作的应用场景,它构成了一道必须被拆除的墙。
第二个不匹配更根本。城市战训练系统需要模拟的不是玩家射击敌人,而是士兵在建筑环境中执行战术任务。这意味着引擎需要理解一些游戏从未建模的物理概念。
一堵砖墙在面对步枪子弹、手榴弹破片和反坦克火箭时表现出的结构响应完全不同。步枪子弹会在墙上留下弹孔但墙体保持完整。手榴弹破片会嵌入表面但不改变结构。反坦克火箭会炸开一个洞口并导致部分墙体坍塌。
在游戏引擎中,这些效果通常用粒子特效、贴花贴图和预设的破坏动画来近似——它们看起来像真的,但底层的几何体和物理属性没有发生相应改变。军事训练需要的是基于材料物理的结构响应模拟:墙体在承受不同载荷时的真实行为,包括应力分布、裂缝扩展和局部坍塌。
研究团队尝试将有限元分析模型集成到id Tech引擎的物理层中。这个尝试在技术上部分成功——他们确实让一堵虚拟砖墙在承受模拟火箭弹时按照材料强度数据发生破裂,裂缝从弹着点向外扩展,墙体局部坍塌并产生符合物理规律的碎片分布。但代价是帧率从每秒六十帧骤降到每秒三帧。游戏引擎的物理模拟被设计为在每帧十六毫秒内完成计算,它假设世界由刚体、关节和简单碰撞体组成。
有限元分析需要求解大型矩阵方程,计算时间以秒甚至分钟计。这不是优化问题,而是架构问题:引擎的物理层没有为连续介质力学预留计算管线,它的数据结构、内存布局和并行化策略都是围绕刚体动力学设计的。
第三个不匹配触及了引擎架构的核心。军事训练系统需要记录和回放完整的训练过程,以便事后进行战术分析——在任意视角下重放、调整时间缩放、标记特定事件、将多个参与者的视角同步对比。
id Tech引擎的网络代码中确实有一套基于帧快照的状态同步机制,最初是为多人游戏的客户端-服务器架构设计的。研究团队发现这套机制可以被改造用于训练回放,但有一个前提:引擎的帧循环必须是确定性的——相同的初始状态和相同的输入序列必须产生完全相同的输出。游戏引擎通常不保证这一点。浮点运算的精度误差在不同硬件上可能产生微小差异。内存分配的不确定性会影响对象创建顺序。多线程调度的时间差异会导致物理模拟步骤的微小偏移。
在游戏中,这些偏差肉眼不可见——一个弹孔向左偏移两毫米没有人会注意到。但在军事训练分析中,弹道轨迹的微小偏差可能意味着命中判定从躯干移到头部,或者子弹是否穿透了掩体的判断发生翻转。研究团队最终提交的技术报告没有公开全部细节。但已知的摘要指出:基于商业游戏引擎构建军事训练系统在技术上是可行的,但需要投入的修改工作量相当于重写引擎约百分之四十的核心代码。这个结论本身就在说明问题:游戏引擎的可移植性不是二进制的是非判断,而是一个光谱。你可以用游戏引擎做游戏之外的事,但每向外推进一步,就需要剥离一层游戏逻辑的硬编码假设。
当美国军方的工程师在id Tech引擎的输入层和物理层中艰难地剥离游戏假设时,一家法国公司正在尝试一种更激进的方案。Virtools成立于1993年,最初专注于虚拟现实开发工具。到2003年前后,它已经发展出一套独特的交互逻辑编辑系统:开发者不需要写代码,而是通过拖拽和连接行为模块来构建三维应用的交互规则。
每个行为模块封装一个基本操作——移动物体、检测碰撞、播放动画、触发音效——模块之间通过连线传递事件和数据。整个应用的逻辑呈现为一张可视化的流程图,可以在运行时实时编辑和调试。
Virtools的架构师做了一个关键的设计决策:将行为引擎与渲染引擎分离。Virtools本身不包含渲染器,而是通过插件接口连接到外部渲染引擎。在2003年的版本中,它支持连接多个商业渲染引擎,包括一个基于DirectX 9的自定义渲染器。这意味着至少在理论上,Virtools的行为流程图可以在不修改的情况下运行在不同的渲染引擎上。
这个设计指向一个更深层的判断:交互逻辑是独立于渲染、物理和音频的第一等公民。在传统游戏引擎中,逻辑层通常以脚本或C++代码的形式嵌入引擎内部,与帧循环、对象系统和事件分发机制紧密耦合。Virtools的架构师认为这种耦合是历史的偶然而非技术的必然。
如果你把交互逻辑抽象成条件触发行为执行的流程图,那么帧循环只是执行这个流程图的运行时环境。理论上,你可以把同一个流程图放到不同的运行时环境中执行——就像Java代码运行在不同的Java虚拟机上一样。但这个理论上同样遭遇了工程现实的阻力。
Virtools的工程师在实现过程中发现,帧循环本身不是中性的容器。不同的渲染引擎有不同的帧循环结构:有的在渲染前更新物理,有的在渲染后更新物理;有的将输入处理放在帧循环的顶部,有的放在中部;有的允许在帧循环的任意阶段插入自定义代码,有的只开放有限的回调接口。
当Virtools的行为引擎接入一个特定的渲染引擎时,它必须适应这个引擎的帧循环节奏——在正确的时刻检查条件、触发行为、更新状态。如果行为引擎的检查时刻与渲染引擎的物理更新时刻错开了一帧,那么碰撞检测的结果可能已经过时,导致行为触发延迟或逻辑错误。更微妙的问题出现在行为模块之间的执行顺序上。
Virtools的流程图允许多个行为模块并行执行,但实际的CPU在同一时刻只能执行一个指令流。行为引擎必须在每一帧内为所有活动模块分配执行时间片,决定谁先运行、谁后运行。在大多数情况下,这个顺序不影响最终结果。但在某些边界条件下——例如两个模块同时修改同一个物体的位置属性——执行顺序的不同会导致不同的最终位置。
游戏引擎通常用优先级系统或依赖图来解决这个问题,但这些方案都假设开发者是程序员,能够理解并管理执行顺序的依赖关系。Virtools的目标用户是不写代码的设计师和美术师。
对他们来说,为什么把模块A拖到模块B上方会导致角色抖动,是一个无法诊断的问题。他们看到的是流程图上的两个节点,看不到的是帧循环内部微妙的时间差和资源竞争。
2004年,Virtools发布了一个针对建筑可视化和工业仿真市场的版本,内置了碰撞检测、摄像机控制和基本物理模拟的行为模块库。
这个版本在欧洲的汽车制造业和建筑业中取得了一定的市场成功——一些公司用它来构建产品配置器和虚拟展厅。但Virtools始终没有真正进入游戏开发的主流市场。游戏开发者习惯了写代码,对可视化流程图的执行效率和逻辑表达能力持怀疑态度。
而Virtools在非游戏市场的成功,反过来强化了它在游戏行业的边缘定位。2005年6月,在苹果全球开发者大会上,一个名叫Unity的引擎首次公开展示。斯科特·福斯托在Mac OS X上演示了Unity的技术特性,宣称其目标是让游戏开发大众化。
这个时间点恰好与Virtools试图将逻辑层从代码中解耦的努力重叠,但Unity选择的路线不同:它不是将逻辑层从引擎中剥离,而是将整个引擎打包成一个对非程序员友好的集成环境。Unity的早期架构在组件系统和场景编辑器方面与Virtools有某些相似之处——两者都强调可视化操作和即时反馈。
但Unity的核心判断不同:非程序员需要的不是完全不用写代码,而是用更少的代码完成工作,并且能立即看到结果。Unity保留了脚本作为逻辑编写的主要方式——最初支持C#和JavaScript两种语言——但将脚本与编辑器的集成做到了前所未有的紧密程度。开发者可以在编辑器中修改脚本中的一个变量,按下播放按钮,立即在游戏视口中看到效果。
这种即时反馈循环实现了Virtools试图用流程图达到的目标——缩短修改逻辑和看到结果之间的距离——但采用了一条不同的技术路径。Virtools试图让逻辑编辑完全脱离代码,结果发现帧循环和执行顺序这些底层细节无法被完全隐藏。Unity承认代码的必要性,但把写代码的门槛降到了尽可能低的程度,同时确保代码修改的反馈循环尽可能短。
Unity在2005年的首次亮相没有立即改变产业格局。它的第一个正式版本只支持Mac OS X,目标市场是独立开发者和小型工作室。
但Unity的出现标志着一个新的变量进入了引擎产业的方程:如果引擎的易用性足够高,开发门槛足够低,那么游戏引擎和交互式三维内容创作工具之间的界限是否会逐渐模糊?这个问题在2005年还没有答案,但它已经被摆上了桌面。
将这三条支流——建筑可视化、军事训练、可视化逻辑编辑——放在一起观察,2005年前后的图景变得清晰起来。这不是三个孤立的跨界案例,而是一种共同的技术意识正在多个领域同时萌发。一批来自不同行业的人几乎同时意识到同一件事:一套能够实时渲染三维世界、处理物理碰撞、管理交互逻辑的软件堆栈,其能力边界远大于电子游戏这个品类。
但这种意识在2005年仍然处于胚胎状态。建筑可视化公司发现用游戏引擎做虚拟漫游需要剥离大量游戏逻辑,而剥离的成本往往高于使用专门的建筑可视化软件——后者虽然缺乏实时交互能力,但工作流程更匹配行业需求。
军事研究机构发现游戏引擎的架构假设与训练仿真的需求之间存在根本性的张力,弥合这种张力需要投入的资源不亚于从头开发专用系统。Virtools试图将逻辑层从引擎中解耦,但发现帧循环、执行顺序和性能优化这些引擎细节无法被完全抽象掉——它们会从流程图的缝隙中渗出来,暴露在那些不理解它们的设计师面前。
这些跨界尝试的共同困境指向一个更深层的问题:游戏引擎的可移植性究竟意味着什么?如果可移植意味着引擎可以不经修改地用于游戏之外的领域,那么答案显然是否定的。游戏引擎的每一层架构都带着关于游戏的隐含假设——从碰撞检测的默认配置到输入设备的接口定义,从帧循环的时间步长到物理模拟的简化模型。这些假设不是缺陷,而是优化:正是因为引擎假设自己用于游戏,它才能在特定硬件上达到实时性能。剥离这些假设就意味着剥离性能。
但如果可移植意味着引擎的某些核心能力——实时渲染、场景管理、交互处理——可以在经过修改后服务于非游戏领域,那么答案不仅是肯定的,而且已经在发生。
真正的问题是:谁来承担修改的成本?引擎开发商、中间件公司,还是最终用户?这个问题的答案将决定通用实时模拟平台这个愿景能否从胚胎发育成成熟的产业形态。
2005年底,Virtools被法国达索系统公司收购。达索系统是工业软件巨头,旗下拥有CATIA和SolidWorks等三维设计软件。这次收购的战略意图很清楚:将Virtools的实时交互能力集成到达索系统的产品生命周期管理工具链中,用于工业产品的虚拟原型评审、装配流程模拟和操作培训。
Virtools的行为流程图被重新定位为三维体验逻辑编辑器,目标用户从游戏设计师变成了工业工程师。收购后,Virtools的技术逐渐融入达索系统的3DVIA品牌,作为一个组件嵌入到更大的企业软件套件中。它在游戏行业的痕迹逐渐消失,但在汽车、航空航天和建筑领域找到了生存空间。从商业角度看,这是一次成功的退出。
从技术角度看,它证明了可视化逻辑编辑确实有超越游戏的应用场景——但前提是必须与特定行业的专业工具链深度集成,而不是作为一个通用平台独立存在。Virtools的故事以它最初试图打破的边界被重新划定而告终:它没有让游戏引擎变得更通用,而是让自己变得更专用。
埃匹克公司在2005年开始收到越来越多的非游戏授权咨询。这些咨询来自建筑事务所、影视制作公司、博物馆、教育机构,甚至一家主题公园设计公司。埃匹克的销售团队对这些客户的态度是矛盾的:一方面,每份授权都意味着收入;
另一方面,这些客户需要的技术支持与游戏公司完全不同。他们没有图形程序员来修改着色器,没有技术美术来优化资源管线,甚至没有专职的引擎集成工程师。他们期望引擎能开箱即用地满足他们的需求——而这个期望恰恰是游戏引擎在设计上没有准备去满足的。蒂姆·斯威尼在2005年的一次内部战略会议上提出了一个方向性的问题。
根据后来多位参与者的回忆,斯威尼指出,如果埃匹克要认真对待非游戏市场,就需要在引擎架构中引入一层领域抽象——将碰撞检测、物理模拟、输入处理这些子系统设计成可配置的模块,让不同领域的用户可以根据需求启用或禁用特定功能,而不是像建筑可视化公司那样手动剥离游戏逻辑。
这个提议立即引发了争议。引擎团队的核心工程师担心引入领域抽象层会增加代码复杂度,拖累游戏开发这一核心业务的性能优化——每一层抽象都意味着额外的函数调用、虚表查找和内存间接访问。销售团队则担心为非游戏客户提供技术支持会分散有限的工程资源——一个建筑事务所的技术支持问题可能需要花费处理三个游戏开发商问题的时间才能解决。
争论没有得出明确结论。但一个问题被正式摆上了桌面:虚幻引擎的未来,是继续做最好的游戏引擎,还是成为最好的实时三维平台?这两个目标在2005年看起来并不冲突,但斯威尼已经预见到它们终将分叉——因为游戏和非游戏领域对引擎的需求在某些关键点上背道而驰。
游戏需要极致性能,愿意为此接受硬编码的假设和专门的优化路径。非游戏应用需要灵活性和通用性,愿意为此接受性能损失和复杂度增长。这个问题在2005年没有答案。
但它被提出的时刻本身,已经标志着引擎产业的一次范式断裂。从1996年《雷神之锤》发布到2004年虚幻引擎3的技术演示,游戏引擎的历史主线一直是更好地制作游戏。渲染管线的进化是为了让游戏画面更逼真,工具链的进化是为了让游戏开发更高效,物理模拟的进化是为了让游戏玩法更丰富。即使在讨论授权模式、跨平台支持和社区生态时,默认的参照系始终是游戏。
2005年的这些跨界尝试第一次从外部撼动了这个参照系。当建筑可视化公司发现墙壁默认是可破坏的,当军方工程师发现输入设备被硬编码为键盘鼠标,当Virtools的架构师发现帧循环无法被完全抽象——这些发现共同揭示了一个事实:游戏引擎不是一套中性的实时模拟技术偶然被应用于游戏,而是一套为游戏深度优化的技术堆栈,其游戏性渗透在架构的每一个层面。
但反过来看,这些跨界尝试也证明了一件事:游戏引擎的核心能力——在有限硬件资源下实时渲染和管理复杂三维场景——确实具有超越游戏的价值。建筑事务所愿意忍受数周的配置调试来获得实时虚拟漫游能力,军方愿意投入相当于重写引擎近半核心代码的工作量来获得城市战训练能力,工业企业愿意收购一整套可视化逻辑编辑技术来增强产品评审流程。这些投入不是出于对游戏技术的爱好,而是因为实时三维交互确实解决了一些传统工具无法解决的问题。
于是,2005年的引擎产业站在了一个分叉口前。一条路是继续深耕游戏领域,让引擎在游戏的边界内做到极致——更好的画面、更快的迭代、更流畅的体验。另一条路是向外扩展,让引擎成为更通用的实时模拟平台——但这意味着要重新思考引擎的架构,剥离或参数化那些游戏特有的假设,承担由此带来的性能代价和复杂度增长。
这两条路不是非此即彼的选择,但它们在资源分配、技术优先级和组织结构上指向不同的方向。
埃匹克、id Software和Unity——这三家公司将在接下来的几年中以各自的方式回应这个分叉口的挑战。而在这一切的起点处,站着一个北京建筑可视化公司的技术总监。他在2003年底盯着屏幕上一堵可以被角色穿过的墙,第一次意识到:在游戏引擎的世界里,没有什么东西是理所当然的。每一行代码都携带着关于世界的假设,而当你试图把这个引擎带到一个不同的世界里去时,那些假设就会变成你必须拆掉的墙。