UE4编成基础
# 框架相关的
# 编程基础
一个游戏是由一个包含所有代码,内容和相关设置的游戏项目定义的。Gameplay代码被包含在一个或多个gameplay模块中,每个游戏项目必须包含至少一个模块。游戏的内容,比如美术资产,声音等等需要被导入到编辑器然后被保存成包和地图,对于游戏可配的设置定义在配置文件中,该文件在启动时被加载,这样就形成了使用UE4所制作游戏的基础。
# Modules
同样地,引擎自身也是由一系列模块组成的。它们和以前引擎中的包相似,它们是一系列相关类的容器。在UE4中,因为gameplay都是用C++完成的,模块实际上是DLL而不是特定包文件。
要想知道如何创建和使用gameplay模块,请看Gameplay Modules (opens new window)。
# ModuleAPIs
函数和类要在模块外面被获取到,需要通过*_API宏被暴露出去。被暴露的每项都需要消耗编译时间,所以确保只暴露必要项。如果一个类中你只获取某一个函数,那么只暴露函数而不暴露类可以明显节省编译时间。
# ModuleAPI说明符
这些说明符是用来将你模块中的DLL函数,类或者数据标记为公开的部分。如果你想将引擎模块中的函数标记为ENGINE_API,那么任何导入Engine的模块将能直接得到这个函数。
它们只在引擎以模块模式编译的时候使用(桌面平台的DLL文件)。除了这个方法,我们可以使用集成模式,将所有的代码放到一个单独的执行文件中。构建引擎的方式是被UnrealBuildTool设置或者被平台,构建的配置控制。
实际的API宏等同下面中的一种,这取决于代码是如何被UBT编译的:
- __declspec( dllexport ),当以模块方式编译模块代码时。
- __declspec( dllimport ),当要包含一个你要导入模块的公共模块头文件时。
- empty,当以集成模式编译时。
API宏只有在模块被其他模块静态导入时才有意义。Core模块就是一个很好的例子,几乎UE4中的每个其他模块都导入Core,并将依赖写到*.Build.cs文件中。
很多模块永远不需要被静态导入(比如SceneOutliner模块),我们将这些模块视为动态加载模块。动态加载模块好的一点是他们在启动时被发现,就像一个插件,经常被频繁加载。
API宏在旧的代码中使用,来让新的模块从它们的DLL中来获取。在较新的代码中,API宏使用的比较少了,取而代之的是用接口层来在DLL之间暴露函数。
# Classes
定义Gameplay类需要使用标准C++头文件和引擎中定义的特殊宏,这些宏有助于定义和UE4相关特殊方面。
# 类的实现
在大部分基本关卡中,你能放置在关卡中的任何任何gameplay对象就是一个Actor。所有的Actors继承自AActor类,这是spawnable gameplay对象的基类。
Actors从某种意义上看可以被想象成是包含特殊类型Components对象的容器,比如一个CameraActor包含一个CameraComponent,一个相机的功能,比如视场都包含在CameraComponent之中。这意味着CameraComponent也可以被包含在其他Actors之中,比如Character,这样就把摄像机的功能给这些对象。
不同类型的组件可以用来控制Actors如何移动,它们如何被渲染,当然还有很多其他功能。所有的对象包括组件,继承自UObject类,这是所有gameplay对象的基类,这就意味着它们不能直接被实例化到世界场景中,要想被实例化到场景中它们得是一个Actor。
每个Actor或Object是一个单例类,这个类为Actor或Object建立起模板。它为Actor或Object定义了可设置的变量和和执行的函数。你可以使用C++代码创建新类,或者Objects或Actors等类型。蓝图主要是让你创建类的实例然后设置值,当然如果你想扩展一个蓝图类也是可以的。你也可以将结合这两种方法,通过创建一个新的C++类然后让蓝图类继承它。
要查看组件更多的内容,请看Components (opens new window)。