关于Mobility,有三种模式:
- Static:This mobility is reserved for Actors that are not intended to move or update in any way during gameplay.
- Stationary:This mobility is reserved for Actors that can change during gameplay but not move.
- Moveable:This mobility is reserved for Actors that need to be added, removed, or moved during gameplay.
UE4的Tooltip里的解释为:
Mobility for primitive components controls how they can be modifed in game and therefore how they interact with lighting and physics. A movable primitive component can be changed in game,but requres dynamic lighting and shadowing from lights which have a large performance cost. A static primitve component can’t be changed in game, but can have its lighting baked, which allows rendering to be very efficient.
UE4里Transform会带一个Mobility设置,用于指定对应的Actor与光照和物理系统交互的方式:
- Movable component会接受动态光照和阴影,渲染消耗是最高的
- Static component就是静态的,可以将其光照和阴影信息烘焙到light map里,渲染消耗是最低的
- Stationary则在二者之间,不会移动,但是会改变,可以使用cached lighting model,比如cached dynamic shadows
The Mobility setting controls whether an Actor will be allowed to move or change in some way during gameplay. This primarily applies to Static Mesh Actors and Light Actors.
PS: 我有次点击Play,进入PlayMode后,发现物体不可以通过Transform对应的三个箭头进行拖拽,但是可以改变Details里的Transform进行改变,后来发现原因是物体的Mobility被标记为static,而不是movable
由于每一个Actor都会有各自的Mobility,介绍Mobility的时候,这里的Actor可以分为两种:
- Static Mesh Actor:就是Unity的带正常Mesh的物体
- Light Actor: 我理解的就是光源
对于Static Mesh Actor而言,Mobility的三种模式功能简单介绍如下:
- Static: 该物体的阴影会事先计算好,存在光照贴图中,而且该物体不可以被移动位置
- Stationary: 该物体的阴影不会事先计算好,而是会实时计算,该物体同样不可以被移动位置
- Movable: 该物体的阴影是实时生成的,而且效果比Staionary还要精细,可以移动位置、被删除和增加
对于光源 Actor而言,Mobility的三种模式功能简单介绍如下:
- Static: 该光源的光会预先生成对应的lightmap,同时参与动态光照计算(应该只是加入进去,像环境光一样,永远不会更改的)
- Stationary:该光源可以改变颜色、强度等属性,但是不可以改变位置,光源既会参与预先生成的lightmap,也会参与实时光照计算
- Movable: they can only cast dynamic shadows,性能消耗较大,但是non-shadowing Movable Lights are very inexpensive to calculate due to Unreal Engine’s Deferred rendering system
关于三种光源的补充介绍如下图所示:
Unity里的自定义Components都是通过MonoBehaviour写脚本实现的,而UE4里提供了蓝图,让用户无需写代码即可自定义Components。
Blueprint可以挂载给任何场景里的物体,场景本身就有一个Blueprint,可以理解为Level的GameManager类,类比于Unity,类似于在Unity的Scene里面挂一个空的Gameobject的Handle,然后挂载脚本。
点击Blueprints下面的Open Level Blueprint,如下图所示:
得到的蓝图如下所示,Event BeginPlay相当于Unity的Start函数,Event Tick相当于Unity的Update函数,如下图所示:
UE4里本身是没有Main Camera这个概念的,为了让Play的画面由指定的Camera的画面显示,需要用蓝图或者脚本进行指定,可以在Level的Blueprint里的Start函数里进行指定,设置游戏开始时的Viewport到场景里拖拽的CameraActor上。
打开Level的Blueprint编辑窗口,右键搜索SetVuewTargetWithBlend
,创建该节点,如下图所示:
这里的Blend可能是在BlendTime里逐步转换画面的意思,这里直接设置为0.0s,意思是瞬间转换View,这里的白色箭头代表函数调用顺序,ViewTarget会从原本的Target转换到New View Target上。
这里的New View Target自然就是新创建的CameraActor了,为了在蓝图里获取它的引用。这里介绍一个把物体的ref拖进蓝图的方式,在打开蓝图的同时,选中场景里的物体,然后在蓝图里面点击右键,选择Add reference,如下图所示:
然后获取原本的Target即可,这里创建GetPlayerController
节点,拖出下面蓝图的样子即可:
再直接进入PlayMode,就可以播放该Camera的画面了
Play当前场景后,会发现场景里多了个球,按WASD可以控制它的移动,这是因为默认的GameMode创建了一个Sphere作为玩家角色。点击Play后,hierarchy里面会多出很多组件,如下图所示:
黄色的都是runtime系统自己添加的东西,DefaultPawn代表默认的玩家,这也是为了方便玩家自己做多人在线游戏的工具(PS:UE4很适合做多人在线游戏)
如果要想去掉默认的GameMode,可以点击Settings打开world settings,如果没有world settings窗口,可以在Window栏下面找到并打开,找到下面的GameMode,如下图所示,想要去掉默认的GameMode,需要自己创建一个空的GameMode,然后Override原本的默认GameMode:
通过蓝图创建一个空的GameMode,然后指定进去,改变Default Pawn Class,如下图所示:
再点击Play,按WASD就不会有任何反应了,此时Play的效果就跟Unity默认的Play效果是一样的了。
Unity’s workflow is based on prefabs. In Unity you build a set of GameObjects with components, then create a prefab from them. You can then place instances of the prefab in your world, or instantiate them at runtime.
UE4’s corresponding workflow is based on Blueprint Classes. In UE4, you build an Actor with components, select it, and click the Blueprint / Add Script button (in the Details panel). Then, choose a place to save your Blueprint Class, and click Create Blueprint to save your new Blueprint Class!
UE4通过蓝图(Blueprint)实现类似Unity的Prefab,感觉也是挺神奇的,这里制作Prefab并不是像Unity那样拖拽到Asset文件夹即可,而是要转换为Blueprint Class
具体做法如下图所示,我之前创建了一个Actor,它带Camera和我自定义的蓝图组件:
选中Actor,这里通过把选中的Actor转换为Blueprint class的方式,存为一个Prefab,如下图所示:
存完之后,会多一个文件,这就是prefab了,可以拖拽很多个到场景里,而且仍然可以用键盘操作让它移动,如下图所示:
打开文件会进入一个窗口,很像Unity的Prefab Mode,如下图所示:
在别人的UE4工程里的Level BP里看到这个,所以好奇这是啥意思:
参考:https://www.youtube.com/watch?v=NwypPq_2hxc&ab_channel=MathewWadstein
这里首先要搞清楚什么UE4的Console Command怎么使用的,它可以在这里的蓝图使用,也可以在Play Mode下使用,在Play Mode下按~
键(按两次可以让窗口更大),可以输入命令,比如输入Stat_FPS
可以看游戏的FPS数据:
视频里还介绍了一些指令:
t.MaxFPS + 数字
:限制最大的每秒帧数r.SetRes + 800*600
:设置分辨率Stat Unit
: 查看包含draw call和GPU相关的每帧信息DumpConsoleCommands
:在output log里打印所有可用的commands,dump是倾倒的意思
至于最上面的图里的,就是另外一种在代码里可以PlayMode下自动执行的(不知道是不是一定是打包后的runtime),通过蓝图来输入,后面有个Specific Player
指令,用于表示Player Controller Reference,用于表示对应的player,适用于多个玩家的系统,像这个关卡就一个Player,所以可以不指定,就用默认的就行。
不进入PlayMode,按~
也可以输入指令,但是一定要注意,这里的Command都是永久生效的,不管你是不是在Play Mode下输入的Commands。
上面提到的ToneMapping的指令,看了下是HDR颜色mapping到LDR颜色范围的东西,跟渲染有关,没多大影响:https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/PostProcessEffects/ColorGrading/
MyClass.generated.h is the include file generated by the UnrealHeaderTool (before UnrealBuildTool compilation) while parsing unreal macros in MyClass.h.All the UCLASS, USTRUCT, UPROPERTY, UFUNCTION macros produce code in the generated.h and so the Blueprint magic can occur in your project with a minimal effort from your side.
相当于把UE4的这些特殊的用于编辑器下的宏,用工具读取出来,生成对应的头文件,就叫.generated.h
的头文件,有了这些文件,才可以在Editor下对其进行操作。
我目前的理解,UE4的蓝图既像Unity的Prefab,又像Unity的MonoBehaviour。Unity里,如果组件A想引用B,那么A里面声明一个public变量,然后在场景里把B对应的Component拖拽到A对应的槽位里即可,或者在代码里Get也行。
参考:https://docs.unrealengine.com/4.26/en-US/ProgrammingAndScripting/ProgrammingWithCPP/ReferenceAssets/
当一个新的Actor的引用被加入到蓝图里的时候,被加入的蓝图里会多出一些该Actor可以使用的蓝图节点选项,具体如何加引用,可以分为如下几种情况:
1. 如果要记录引用的蓝图是Level蓝图,而且被引用的Actor在Level里
这种情况下比较简单,鼠标选中场景中的物体,在关卡蓝图右键添加引用即可,直接从场景里拖物体进去也行。
2. 使用函数,当Actor在level里被创建的时候,获取其引用
比如说我有一个角色的蓝图, 场景里有一个负责枪口粒子特效的Actor,我想获取它的引用,那么需要使用函数,在该Actor被创建的时候去获取。在角色的蓝图里,创建一个Spawn Actor节点,选择对应Actor的类型Blueprint_Effect_Fire
,然后把节点连接到角色的Event Begin Play上,如下图所示:
目前这个操作,其实是创建了一个Actor,并且将其位置放置在了Player的Transform上,目前二者是拥有的关系。
接下来,从Return Value往外拖拽,选择Promote to Variable:
这样做,就可以把它作为Variable,在该蓝图里随便使用了。这种方法,其实只是在蓝图里创建Actor,然后把它的引用作为变量记录在蓝图内而已,还没有涉及到蓝图之间的引用。
3. 蓝图之间的直接引用(Direct Blueprint Communication)
假如Level里有两个蓝图物体,一个是火焰A,一个是火光B,想要的效果为,游戏开始时,两个都存在,但是2秒后,A来控制,把B给Deactivate,那么此时A要记录B
打开A的蓝图Blueprint_Effect_Fire
,给它添加一个蓝图变量,搜索火光B对应的类,进行添加,如下图所示:
把这个变量命名为Blueprint_Effect_Sparks_C
,注意,在UE4里,_C
代表引用,应该是const ref吧。
Reference Blueprint Actors are denoted with a _C following their name as seen above.
把这个变量拖拽到蓝图里,然后就可以调用它里面自己的public函数了,如下图所示:
到目前为止,已经在A里创建了B类型的变量,但是目前还是没有把场景里的B实例和A里的B引用绑定到一起,此时编译会报错: