虚幻提供许多编辑器
蓝图与C++
虚幻支持的文件内容
| 分类 | 类型 |
|---|---|
| 3D | fbx/obj |
| 贴图 | png/jpge/bmp/tga/dds/exr/psd/hdr |
| 声音 | wav |
| 字体 | ttf/otf |
| 视频 | mov/mp4/wmv/avi |
常规使用的文件格式一般都支持
显示UE的资产
UE推荐的文件分类文件夹命名
设置文件夹颜色,帮助分类
光源
光源的移动特性
光照模式
间接光照是真实世界的光照重要组成部分
构建光照可以获得间接光照缓存(光的颜色贴图),这样运行时直接使用该贴图即可
当你对场景进行构建的时候,会进行光照收集(光量子收集),收集这片区域每个点上的光亮强度,记录光的颜色。当移动物体在区域内移动的时候会把颜色贴到物体表面上从而产生照亮效果。
当物体在场景中移动的时候,其实就是在光照贴图中找对应区域的颜色,然后把颜色贴到物体表面上去(给人感觉像是照亮罢了)
蓝图时虚幻4中的一个可视化编程语言。具备传统编程语言的特点,同时具备简单、易用、易理解的特性
种类
Actor(演员)
在目标文件夹(一般是新建名为BluePrints的文件夹)中右键,新建蓝图即可
在编辑器视口中,按住鼠标右键拖动
在编辑器是口中,按住鼠标左键拖动可拖出节点或执行线
按住alt键再点击连接线,可删除连接线
安卓ctrl键再点击连接线,可重新选择目标节点
读取蓝图的时候,从白色执行线的起点开始,顺着执行线一个蓝图节点一个蓝图节点的读取即可
事件类型
创建的蓝图对象直接拖入到场景中并不会被渲染出来,需要添加网格组件才可以被被渲染出来
关闭每帧执行的tick Begin Play(事件开始运行的执行 先于 Tick每帧调用)
想创建一个朝固定方向移动的球体
AddActorWorldOffest节点,设置参数日志可以提供运行时态的程序信息,并进行输出 通过查看日志来查看对象状态,以反馈数据内容
比如查看玩家具体速度数值、根据数值异常查找bug、判断逻辑是否执行等
打开日志窗口
在日志窗口中,可以右键清除日志
选中注释,点击键盘del即可删除
功能类似构造函数 只要蓝图对象被构建、调用,则该函数就会执行
当你在编辑器窗口拖动时,虚幻会认为你要重新构建该物体,所以物体的构造函数会被执行
通过图片上的设置,可以关闭拖动时重新构建调用构造函数
一般将调整信息逻辑放入到Construction图表中,只要在场景中物体被移动,Construction就会执行,物体会自己重新设置自己
在编辑器模式中拖拽蓝图对象会调用Construction,但是在真正的独立发布软件上使用代码控制对象不会执行Construction,也即发布后的软件上只在最开始的时候调用一次Construction
选中目标变量,将其拖入到蓝图的视口中,可以选择使用get/set方法
直接在视口中敲击 +、-、*、/、%即可进行对应运算
基本数据类型中,字节型、整型、浮点型均支持常规数学运算,即加减乘除
执行顺序是事件开始->设置Age的值->Print1->Print2
Age的初始值为5
当执行到*设置Age的值*时,根据针脚指针往回推导,开始计算,最后设置Age的值为40
当执行到*Print1*时,直接获得setAge的值为40
当执行到*Print2*时,根据针脚指针往回推导,开始计算,最后获得输出值为215
Print2时,Age的值已经被改变了 所以Print1和Print2的输出并不相同
整型数据的自增自减
常见流程控制
判断是否成年
允许逻辑执行先进行分割,但不是并行关系,而是次序关系,最上层位于运行上端,以此类推 序列支持多个次序执行线并存,通过增加引脚来增加次序执行线 序列中的逻辑执行针脚是按照次序一次执行 目的是来帮助开发者将逻辑进行划分,可以将逻辑分成几块,而不必非要串联到一条逻辑线上,达到清晰逻辑结构的目的
Do节点用来控制当前执行逻辑线进行连接后,视口可以通过输出逻辑针脚将逻辑执行权向下进行传递,主要用来控制执行权通过次数
Do N可以用来制作开枪,比如枪管只有20发子弹,只能发射20发;有的武器只能发射一次,则使用Do once
Do Once节点中的Start Closed表示初始是否是非激活状态,勾中表示一开始Do Once节点就是失效的不会执行后续操作
Do Once,最开始是激活状态,所以会输出字符串1Do Once之前已经执行过一次了,所以不会执行后续操作Do Once节点,使之重新进入激活状态Do N,设置Do N节点的N为5,所以点击五次3,才会使Do N节点失效Do N节点的次数与DoOnce节点基本相同,但是可以通过添加新的引脚,增加独赢的输入逻辑,只要任意逻辑输入针脚有调用,则整个节点被关闭
通过调用重置输入针脚重置整个控制节点
这里A、B、C中任意一个被执行了,另外两个都不会再次执行,除非重置整个
Do Once MultiInput节点
节点取入执行输出并在两个执行输出间切换
节点同时有bool变量输出,可以用来判断A何时被调用(执行A返回true)
例如:第一次被调用执行了A,则第二次被调用执行B,然后再是A,然后再是B
实际运用:开关灯
按照从First Index开始,到Last Index结束,调用逻辑输出引脚Loop Body,调用次数为First Index到Last Index差值
Index输出参数引脚将输出从开始到结束的所有整数,当整个节点执行完毕后,调用逻辑输出引脚Completed
常用于叠加计算,或多次执行某个动作 等价C++代码中的
for关键则
输出5 6 7 8 9 10 Complete
与ForLoop相同,用于将单词执行逻辑进行循环
但添加了Break输出引脚,如果被打断则直接停止循环,跳到输出逻辑引脚Completed
使用for循环计算1~100的和,当和超过1000的时候停止计算
当和超过1000时,分支语句Branch为True的针脚向后执行,Break掉ForLoopWIthBreak,随后直接输出计算和1035
用来控制开启和关闭的执行逻辑
Enter输入逻辑进入
Open引脚被调用后,Enter引脚流入的执行逻辑才会从Exit引脚流出
Close引脚被调用后,Enter引脚流入的执行逻辑将被阻挠,无法流出
Toggle从开和关之间进行往返
Start Close设置节点开始状态,勾选后开始状态为关闭
最开始
Start Closed为选中状态,所以Gate处于关闭状态,点0无反应
点按钮键盘1之后,Gate打开,再点击0执行输出Toggle
点按钮键盘2之后,Gate关闭,再点击0,无输出
点按钮键盘3之后,Gate如果原本关闭则变为打开,如果原本是打开则变为关闭,再点击0,根据状态判断是否输出
输入逻辑节点将按照顺序或随机方式从右侧输出引脚进行输出执行逻辑
Reset 重置整个节点,使之回复到起始状态
Is Random 勾选引脚,按照随机的方式从右侧输出引脚选择输出执行逻辑
Loop 勾选引脚,按照循环方式从右侧输出引脚输出执行逻辑
Start Index 设置第一调节用节点从右侧那个引脚进行输出
只要不勾选
Loop,则每次执行MultiGate会把逻辑引脚依次全部进行一次输出(不会重复输出)
如果
Is Random和Loop都没勾选,则多次点击键盘按钮会输出一次Out 0,一次Out 1,然后MultiGate关闭
如果只勾选了Is Random,则多次点击键盘按钮1会随机输出一次Out 0或Out 1
如果只勾选了Loop,则多次点击键盘按钮1会循环输出Out 0,Out 1
只要特定值Condition为true,则whileloop节点将会输出一个结果。在循环的每个迭代中,他会查看器输入bool值的当前状态,一旦为false,则停止循环
等价C++的while
SumValue初始值为0,每次都SumValue = (SumValue + 1) * 2,当SumValue小于100的时候执行循环体,大于100就跳出循环,最后输出SumValue的值为126
当逻辑输入针脚被调用时,将会按照给定的值Selection进行右侧选择引脚输出
功能等价于C++的switch
如果值为1,打印执行值为0对应的第一个Print
如果值为2,打印执行值为1对应的第二个Print
如果值为3,打印执行值为2对应的第三个Print
如果不为1、2、3,打印执行Default对应的Print
Delay节点,延时操作
当延时任务未完成时,再次调用节点,忽略调用
尽量不要将Delay节点让如Tick中
Delay只能在事件表中使用
Duration延时动作持续时间
Retriggerable Delayer与上面的Delay的节点一致,只是如果延时任务没有完成,再次调用节点,则延迟动作重新计时
不停按键盘按钮4和键盘按钮5可体会
Delay和Retriggerable Delayer的差别
面向对象的特性为封装、多态、继承
我们创建编写的蓝图,称之为蓝图资产或蓝图模板
模板是用来产生真实对象的,同时模板也是一种数据类型,一种复合数据类型,主要是用来描述对象的结构和行为,这也被称为抽象
蓝图变量框添加的变量,称之为成员变量
成员变量是抽象为对项目模板而添加的,只能通过蓝图的实例化对象才能有效访问该成员变量
成员变量描述了抽象的对象的属性信息
在制作触发器的时候,Box Collistion是不容易看见的,这个时候给触发器一个Billboard组件,该组件仅提供一个显示作用,方便查找
这里场景编辑器就是前面说的关卡编辑器,写急了
函数:一段在一起的,可以做某一件事的程序,也称作方法。函数是面向对象中将逻辑进行封装的重要表现
编写函数的目的:将逻辑单一化、清晰化、明确化、复用化,加强整个结构的可阅读性
编写函数可以提高工作效率,函数本身可以用来处理数据也可以辅助获得数据
将属性和函数编写在模板中,体现的就是封装
函数中不可调用
Delay,因为函数执行是一瞬间的,执行完就没了
蓝图中函数允许多个返回值
如果执行线最后没有连接到返回节点中,也不会报错,会返回对应数据类型的默认值
编辑器调用功能一般用于测试功能
函数细节有个扩展按钮,点击后里面有个常量框,类似C++的const void funcion() const,表示函数中对对象属性的值不会有更改
只在函数中有用的临时变量
Event事件只能在事件图表中进行构建,无法在函数、宏内进行构建
事件如函数一样可以在外部被调用,支持输入参数列表编写(函数中可以调用事件)
添加自定义事件
与Event Begin Play节点很像
事件没有输入引脚
类似C#的Event,红色节点
ChangeSpeedEvent表示事件触发后蓝图对象所执行的操作
蓝灰色节点ChangeSpeedEvent表示广播事件触发
宏本身进行的是节点替换,过量使用宏会导致程序的节点量膨胀
宏的优点:
所有的对象类型变量使用前均需要通过
IsValid节点进行安全检查,增加程序的稳定性
IsValid节点接受一个对象型(Object)数据
事件调度器是蓝图中按照观察者模式(订阅)而添加的。观察者模式是较常使用的的一种设计模式,它具有高效低耦合特性
在整个设计链上,采用有动态状态改变时主动发出通知,从而达到订阅特性
观察者模式应当构建对象,应该将对象想象为观察者和被观察者
graph LR
A[分发器] -->B(订阅者A)
A --> C(订阅者B)
A --> D(订阅者C)
A --> E(订阅者D)
观察者是希望接受被观察者的响应,所以响应逻辑(动作)一般写在观察者身上
事件应该在下希望接收通知的对象身上,调度器写到发出通知的人的身上
比如:A想知道B的工作是否完成,如果每帧都去询问无疑会增加许多无效计算浪费性能
这个时候使用观察者模式,B是被观察者,A是观察者。B工作完成之后发送事件,A接收到事件做出对应逻辑(动作)
创建事件调度器
注册监听
解除绑定
解除绑定的具体做法
Of Class通过给定的ui想模板将场景中与之匹配的对象进行查找,并返回查找到的所有对象
With Interface 通过给给定的接口将场景中与之匹配的对象进行查找,并返回查找的所有对象
With Tag 通过给定的标签将场景中与之匹配的对象进行查找,并返回查找到的所有对象
蓝图中的结构体只有属性,没有函数
创建结构体
设置结构体参数
使用数据结构
使用make 结构体名称可创建结构体对象
某些有穷序列集的所有成员,例如:性别(男女)、月份(1,2,3,4……)、星期(1,2,3……)、学历等
创建枚举
设置枚举
枚举配合Switch使用,做分支判断处理
创建数组、map、set
这里需要先定义属性的数据类型,再设置其属于array、map或set
数组的循环遍历
获得数组中index序号位置的值
Get方法有两种获得值的方式:复制、引用复制:完全隔离,获得到的数据与原数据没有关联
引用:实际上获得的就是数组中的对象,对获得的对象进行操作会改变原数组的对象
Add方法分为两种:Add Unique和普通的纯Add
Add Unique:添加的值数组中存在,则不添加
Add:不管容器中是否存在,都添加到数组末尾
查看数组的API方法的小提示
| 方法名 | 作用 |
|---|---|
| Add | 添加单个数据到数组末尾 |
| Add Unique | 如果数组中没有与数据相同的值,则加入到数组中,否则不加入 |
| Append Array | 将另一个数组添加到数组中(不考虑重复性) |
| Clear | 清空数组并清除内存空间 |
| Contains | 检查数组中是否存在给定值 |
| Find | 查找数组中是否包含某一个元素,包含返回对应位置索引index,不包含返回-1 |
| Insert | 插入值到数组中(指定位置) |
| Last Index | 获得最后元素的值 |
| Length | 获得数组长度,常用来判断获取index是否合法 |
| Remove Index | 提供一个有效下标index,删除该index |
| Remove Item | 提供一个数组中包含的数据,删除该值 |
| Resize | 设定数组长度,超过填充默认值,小于删除多余值 |
| Shuffle | 随机数组中的值(洗牌) |
| Swap | 将数组中已有的两个位置的值进行交换 |
使用Make Array可以在运行过程中动态创建数组
物理引擎通过为刚体赋予真实的物理属性的方式来计算运动、旋转和碰撞反馈
游戏引擎中的物理引擎的主要目的是为了解决物体在空间的状态信息
常规的物理引擎遵循物理定律,按照给定的算法,进行模拟物理运动。所以在没有多元因素影响的状况下,物理引擎的计算结果是一致的,与现实世界基本一致
虚幻使用的是 PhysX3.3的物理引擎驱动物理仿真以及碰撞计算
物理引擎模拟物理计算,增加游戏的代入感,是的玩家与场景之间能够进行基于物理的交互(碰撞,发力等)
物理引擎本身处理了物体与物体之间的交互关系
所有的物理运动以及碰撞都有PhysX管理,在游戏中模拟物理将有助于提高每个场景的沉浸感
碰撞响应和追踪响应(射线)构成了虚幻4引擎在运行时出冷碰撞和射线投影的基础
碰撞检测和射线检测
虚幻中的碰撞交互分为三种
产生物理交互的必备条件:刚体(包裹外壳),如果希望加入物理引擎运动,还需要开启物理模拟
虚幻引擎中,物理碰撞添加的途径有两种:
静态网格分为简单碰撞和复杂碰撞
打开网格编辑器,查看复杂碰撞和简单碰撞
可以看到绿色的框就是物体的相似接近于桌子的形态,这就是虚幻的K-DOP包裹
添加简单碰撞
虚幻提供三种简单的形状碰撞器:球体、胶囊体、盒体
虚化允许一个物体具备多个碰撞器
K-DOP是包围体的一种,是K离散导向多面体(K discrete oriented polytope)的缩写(K是轴对齐平面的数字)。它抓取轴对其的平面,将其尽力推向离网格体最近的位置
自动凸包包裹也属于简单包裹,同过程进行计算获得包裹数据信息。需要调整凸包顶点的最大数量。
凸包数量:决定了包裹物体需要使用的凸包个数,越多越精确,消耗也越大
最大外壳定点数:每个凸包最大允许使用多少个顶点
凸包精致度:使用多少模型面做计算参考,数量越大精度越大
基于物体的形体轮廓(mesh三角面)进行计算
使用简单的物理碰撞制作成复杂的物理碰撞,是常用的设置物体物理碰撞的方法,因为简单的物理碰撞计算效率最高
从GIF中可以看到,如何删除物体的碰撞体积,如何添加物体的碰撞体积