引擎结构
可使用不同的方法来建立游戏架构,这些方法既有一体化的解决方案也有众多单独模块法解决方案。在一体化解决方案中,游戏逻辑同引擎混合在一起,而在后者中每个单独的模块负责函数中的一部分。而Unigine则提供一种较为折中的方法。除开应用逻辑,网格和AI,它将实施游戏或其它3D应用程序的一切所需合并在一起。Unigine中仅包括用于所有应用类型的典型游戏逻辑和普通逻辑。当然我们是有意执行这样的操作。
也许看起来这并不算是一种优势,因为一旦要打造一款游戏就需要执行大量的编程并需要使用在所需类型游戏中被广泛使用的普通函数。然而,缺少指定类型的游戏逻辑也并没那么糟,因为这样Unigine便成为了一个多用途库,可在不同的项目中较容易地进行重复使用。此外,开发者并非一定要对类型进行指定,他们可以立即试用数种类型,但如果使用了某种专用引擎,这样的操作就很难。例如要将枪手和仅用于第一人称射击游戏引擎范围外的竞速游戏结合在一起就显地很困难。当然,Unigine可以对外部模块进行阻塞,这些模块可包含指定类型的函数并可被再次使用。这些Unigine就成为一个极其灵活的库可用于各种不同的3D应用程序。
对于开发者及内容创建者而言,了解Unigine的结构十分重要。开发者可以知道他们可以在Unigine进行的操作,可以实现的内容以及能对Unigine寄予什么样的期望。而对于内容创建者而言。他们可以知晓内容的处理方式。这也正是本文会对Unigine工作流进行简要高级概述的原因。
下图对Unigine内部组件与不同的外部实体间的相互作用关系进行说明。
当定制应用程序逻辑 调用Unigine API函数时,所有组件便被启动。可直接通过UnigineScript或 C/C++ 完成这些调用过程,前者更可取因为这种情况下程序员不必考虑到多线程以及内存管理。当然如果此应用程序被写在UnigineScript中,那么将在Unigine支持的每种平台上运行此程序。如果应用逻辑对函数扩展作出要求,那么API组件会加载对Unigine函数进行扩展的modules(模块) 。例如这种模块可能包含第三方中间软件。
API的调用会被传递给解析器,这样便完成对所需资源的初始化操作:注册扩展,加载核心数据、配置文件、脚本及用户接口文件。由于这些资源都被组织在一个特殊的数据目录中,并可被打包,通过文件系统组件对这些资源进行加载。此外,文件系统组件会追踪文件的字节顺序。请注意如果在初始化完成之后要将文件添加到此目录中,需要重新加载文件系统组件。
初始化之后world manager(世界对象管理器)便开始起效。管理器会加载用来建立当前场景文件并决定可视节点集,此节点集稍后会被发送给render组件。世界对象管理器同样也会传递信息给sound 组件,这些信息包括播放环境声音的时间及方式,放置在世界对象中的资源种类及具有空间特性的资源。当然管理器也会与physics组件相互配合,此组件执行物理计算(碰撞检测,关节处置,流体浮力等)及在可能的情况下对节点分级进行升级。简言之,世界对象管理器自身并不会绘制对象,播放声音或者执行物理计算,它只是将这些任务委托给指定组件。
着色器组件和声音组件需要额外的资源才能完成各种的任务:着色器组件需要纹理,网格及动画,而声音组件需要声音。因此这两种组件会要求resource manager(资源管理器)提供它们所需内容。加载所需图像和声音是资源管理器的任务所在,如果不再需要这些图像和声音,那么同样资源管理器也应当对这些图像和声音进行缓存然后卸载。资源管理器的存在使得游戏开发者不必在考虑数据加载及卸载的方式及时间。
如果要求应用程序逻辑发出指示,解析器可能会调用GUI组件并使用此组件通过着色器组件绘制用户接口。而在Unigine中,GUI对象不仅可以是独立的还可以是展示的虚拟世界中的一部分。这样地话如同其它节点一样这些GUI对象将被世界对象管理器管理。
当把可能包含有GUI的渲染图像呈现给用户时,这样便开始于世界对象产生互动作用。用户可通过不同的输入设备对世界对象产生影响。从这些设备上的输入会被穿传送给GUI组件和controls(控制)组件。GUI组件会处理这些输入,检测所点击的原色并执行相应的回调函数。控制组件会处理与GUI无关联的输入,例如游戏中玩家的动作。请注意GUI组件会始终先于控制组件获取输入数据,因此具有更高的优先级。
th如果用户的行为影响到渲染或物理设置等,经处理的输入会传送给探测到的解析器。如果如此,解析器会要求对应的组件对图像或计算进行更新升级。如果用户的输入造成世界对象中发生了些许变化,世界对象管理器会对可见节点集进行更新升级并将新的请求传输给委托的组件。
这些动作会在一个周期内重复直到用户停止使用此应用程序。