游戏引擎如何设计与架构

发布时间 2023-11-16 10:07:34作者: rain4414

 以前做过游戏引擎,也看过几个商业引擎的源码如Torque等,还有用过一些第三方的引擎来开发游戏,如Unity, Cocos, Laya等,今天来说一说一款游戏引擎应该如何架构和设计,我做了一张图,如下,接下来讲围绕这张图分三个层次来给大家讲解一个游戏引擎的架构与设计。

  

 

OS平台抽象层

  游戏的本质其实就是运行在OS上的一个App,所以游戏使用的各种系统支持和系统调用都是基于OSAPI函数来完成的。而现在的游戏引擎都要求跨平台,一次开发能打包发布到Android, IOS, Windows, Mac, Linux等。游戏引擎首先会做一个平台抽象层,这层主要包含两个方面: 

(1)给游戏引擎提供统一接口的OS系统调用;

(2)是给游戏App打包发布提供的发布工具与发布环境。

平台抽象层主要提供以下功能:

   App支持:创建一个游戏窗口,游戏App有个窗口的载体;

   事件支持:  调用OSAPI获取OS的鼠标,键盘,触摸,重力感应等操作事件;

   声音支持:  调用OSAPI来播放声音;

   文件IO支持: 调用OS的文件操作API,提供文件的读/写等功能;

   平台API调用支持:调用手机相册等;

   网络支持: 调用OS的网络接口来做网络通讯;

   SDK支持: 提供SDK的接入的机制;

   OpenGL支持: 提供平台的OpenGL环境的支持;

这些功能对外开放统一的接口给上层调用,对内有不同的平台都有不同的一套实现,所以跨平台的游戏引擎不同平台都有对应的项目与工程,游戏打包的时候,不同平台用平台特有的App工程来打包。有了平台抽象层,跨平台这件事情就解决了。为做游戏引擎内核打下了坚实的基础。

   

 

引擎内核层

  平台抽象层写好以后,就基于平台抽象层提供的OS的接口支撑来做游戏引擎的内核,游戏引擎的内核包括主要的以下几大模块:

   主循环: 游戏引擎其实就是一个循环,大致的伪代码如下

      mainLoop() {

           接收输入,并处理;

           迭代游戏场景中元素的update,处理逻辑;

           提交给GPU,渲染绘制游戏一帧画面;

           维持合适的帧率,如果CPU有空闲适当的休眠。

}

   渲染管线与Shader: 基于OpenGL/DirectX等构建渲染策略与渲染管线,给用户提供Shader开发机制,渲染策略不一样,一个游戏引擎可能有多种渲染策略(渲染管线),比如向前渲染,延时渲染,像Unity还有可编程渲染管线,基于可编程渲染管线又推出了高清渲染管线与轻量级渲染管线。每个渲染管线与策略都有对应的Shader的机制来配合,提供一个编写Shader的机制给用户,能做Shader的开发。

   事件输入: 接入OS平台事件,然后来派送事件到具体的节点或是作为系统事件上报给应用层。

   网络模块: 游戏开发中的网络就是长连接Socket(H5websocket)http协议,所以这块我们也要支持好,SocketOS提供的API,只要通过平台抽象来调用就可以了,http我们可以使用一些第三方的库来做http协议的编码与解析。

   文件IO:面对应用层提供一些接口出来,然后调用平台抽象层的底层的文件IO的系统调用,来完成文件IO的服务。

   声音模块:面对引用层提供一些接口或组件,然后调用平台抽象层来发出声音。实现播放声音文件,支持对应的声音格式,如wav, ogg, mp3等。内置这些常用的声音格式的解码库。

   场景管理: 游戏引擎基本上都是基于场景+节点的模式,节点在场景中以场景树的方式组织起来,然后基于这个做好矩阵等相关数据结构与代码,管理好场景中每个节点每个物体的位置等相关的信息。

  组件化开发模式:目前组件化开发模式是游戏界主流的一种模式,unity, cocos, Laya都采用这种方式。所以引擎设计一套组件化的开发模式机制,以及开发出一些公用的组件,比如UI组件或3D骨骼动画组件等。在游戏引用开发中这些组件都可以直接使用。同时还会提供一些粒子特效播放等。

  物理引擎:游戏开发中经常要用带物理引擎来模拟真实的物理计算,目前大部分的游戏引擎的物理引擎都是内置第三方的,如: libbullet, PhyX, Box2D等。

  客户端脚本:脚本系统基本上是一个游戏引擎的标配,游戏引擎的内核大部分都是基于C++来实现,而C/C++代码开发难度比较大,为了能降低游戏开发的门槛,提升开发效率与速度,一般都会提供脚本语言来开发,就需要内置一个脚本解释器。有些脚本是引擎自己定义的比如Torque,有些内置了轻量级的开源第第三方脚本,如Lua,Python, JavaScript等(Unity内置的脚本C#)。同时还要把游戏引擎的接口导出来给脚本使用。

这些模块开发完成以后,基本上游戏引擎的内核就完成了,包含了底层架构和给用户提供开发模式。给用户提供的开发模式机制,直接决定了你引擎是否好用,主流的现在是组件化开发,所以现在很多游戏引擎都提供的是组件化开发的机制。

 

游戏应用层

  游戏引擎内核设计好了以后,基本上就可以基于这个引擎来使用纯代码来开发游戏了。然而使用这个游戏引擎内核第一次做的App并不是游戏,而是游戏引擎编辑器的App。基于游戏引擎内核开发一个用户可以编辑的”游戏”,资源管理,日志管理,属性查看,编辑器扩展,粒子编辑工具等功能的一个工具性质的App。有了这个App就可以可视化的编辑游戏场景,动画,动作,特效等,同时还可以基于这个App来编写和开发代码。这些编辑的场景与资源都生成到资源文件里,运行的时候,游戏引擎内核把他们当作资源加载运行。最后就是打包发布,游戏引擎App还会内置不同平台的打包工具,让用户直接可以通过App可视化打包,降低开发难度。游戏引擎编辑器App开发完成后,就可以正式交付游戏厂商使用,开发出各种不同类型的游戏。

 

 

 

为什么引擎厂商开源内核源码但不开源编辑器

   最后给大家分享一个游戏引擎行业的一个有意思的现象,为什么很多游戏引擎可以开源游戏引擎内核源码,但是不开源引擎编辑器源码呢?比如Cocos, Laya等。这里分为免费游戏引擎与需要授权的引擎,免费游戏引擎如Cocos, Laya,引擎内核代码直接开源但不开源编辑器,这样做的理由是开源内核代码你可以定制修改引擎底层代码与引擎底层的bug。不开放编辑器是大部分的游戏都是基于编辑器做的,如果开放编辑器的源码,可能一个社区就会出现很多不同的分支,比如以前cocos-lua的社区后来又出了一个quick-cocos-lua的社区,这样让整个版本的更新迭代不受掌控,有分裂的风险。对开发者来说未必是好事。商业授权代码的引擎,本身商业授权就有资金门槛,同时还有保密协议,相对来说好会更好控制。

 

  好今天的游戏引擎框架设计就给大家分享到这里,要做一个好的引擎确实不容易,给引擎厂商点赞,特别是免费的引擎厂商。