ue4 学习记录

开门练习

1.盒体触发器:感应装置(用门举例,感应什么时候开门/关门)。
2.事件:为组件添加事件来达到交互的目的(onActorBeginOverlap :开始触发事件,onActorEndOverlap:离开触发事件)。
3.引用:让系统知道事件作用于谁(如开门/关门时,引用对象为门,是让门开/关)。
4.让门旋转:setActorRatation表示actor内所有组件都旋转;setrelativerotation设置局部坐标系下的相对位置旋转;setworldrotation设置世界坐标系下的旋转(世界坐标不会被改变);
5.时间轴:用于过渡,让画面不会那么生硬。点击函数fx,右键添加关键帧设置时间与数值,需要几个关键帧就设置几次;选中关键帧节点右键使用自动进行平滑;注意:上方长度要改为我们设置的时间长度;如开门/关门(第一个关键帧(时间为0,值为0),第二个关键帧(时间为2,值为85)。用2秒开门,开85°的门。
6.play:正向播放,reverse:方向播放,update:更新(每帧美妙的进行更新),新建轨迹与相对应的值相连。play from start:从设置的第一个关键帧开始播放,set new time:自定义播放时间,direction:时间轴方向的判定。
7.Actor:在世界中可以放置或生成的对象。

创建门的蓝图类

Actor和组件区别、门的轴心点修改

1.创建一个蓝图类,在添加组件栏目添加静态网格(staticMesh),静态网格相当于模型,并对其赋予对应的网格体组件进行组合;
2.此处的碰撞触发器叫做BoxCollision合体碰撞(感应装置);并将其与门放到同一级,避免随门一起动,并且若不和门同一级,开关门也可能检测到重叠事件,产生bug;
3.Gate节点:用于流程控制,open相当于插入钥匙,close相当于拔出钥匙决定Gate是否有后续执行;当有了钥匙状态之后通过操作Enter往后执行(处于open);有关对Enter的操作可以使用键盘,此时会用到节点Enable Input或者Disable Input,有关玩家控制使用playercontroller;
4.键盘输入:keyboard +具体哪个键盘值,Enable Inpu:允许输入,Disable Input:禁止输入。
5.按键响应需要有控制器
6.flipflo:执行第一次走a,执行第二次走b,第三次走a,......
7.鼠标点击:on clicked,然后要开启控制器中的点击事件

进行以下设置

1.Enable Input(启用输入)

2.Disable Input(禁用输出)

3.Get Player Controller(获取玩家控制器)

【以上三个组合总而言之就是规定了一个控制角色(Get Player Controller),确定了蓝图可以接受或拒绝操作该角色的玩家从键盘发出的指令:启用输入(Enable Input)禁用输入(Disable Input),一旦该角色满足了触发条件,就启用输入或者禁用输入,即该角色可以获得或者丧失从键盘(这个案例是,下面那个案例是鼠标,总结总结应该接受从设备输入)输入按键的权利,然后触发后面乱七八糟东西的】

4.E【就是按键E】

5.Gate【门,就是当怎么样(在Open或Close满足时)的前提下然后怎么样(Enter个啥玩意)的时候允许触发事件】

6.Flip Flop【切换翻转,就是A和B轮流执行,第一次调用执行A,第二次B,第三次A……】

按键开门具体蓝图:

Set Show Mouse Cursor【设置显示鼠标光标】
On Clicked(点击时)【在需要点击才会触发的组件最右侧细节面板中的事件里找!】
鼠标点击开门完整的蓝图:

注意:要想激活鼠标单击能触发事件,还需要做一个工作:

升降电梯

1.Lerp插值(由A、B、Alpha三部分输入节点和一个Reruen  Value输出节点组成,A、B进行数值从A到B的变换过程,A为起始值,B为最终值,Alpha控制A到B转化到了什么程度,类似于进度条从0到100%(即0到1)的转化,Alpha可以和前面的时间轴输出轨道相连,即用时间轴在多少秒内其值从0到1来控制Alpha,用于位置移动,有一个很好过渡效果,A填写电梯位移初始值,B填写电梯位置末值)
 2.用了lerp后,时间轴里面可以不设置值。这样时间轴就可以用于设置任何对象,有多个需求时可避免创建很多个时间轴轨迹或者时间轴
具体蓝图

注意时间轴是怎么和后面连线的,时间轴连左侧门,左侧门连右侧门,但是左右两个门要分别设置插值去控制它们位置的变化。

有个坑!由于盒体碰撞检测器会因为门的运动而被再次触发,所以会产生bug(例如在门正在开的同时往门里走,会导致无法触发关闭,必须再次走出来),所以要将两扇门的细节面板中碰撞栏里的“生成重叠事件”对号取消掉。这样才可以保证盒体碰撞检测器不受两扇门的运动的影响。(门的运动也会被算为重叠触发!)

双开门

(此时只需要设置你想把门开到多大即可,不用再手动调初始和结束位置)

通过获取组件一开始位置的方法,将组件的初始位置存储在一个变量中(变量在左侧新建),然后通过再次新建一个变量输入想要移动的参数,用加法(Float+Float)实现门的移动。

此蓝图有bug,因为.Get Relative Location所连接的变量所处的连接位置在触发按键之后,所以一旦在开门动作中(即开关门动作未完成时)再次按键,则会将当前位置存储在变量中,那么再次触发时将不再是我们希望的起始或者结束位置,从而产生bug。

新的节点:

1.Get Relative Location(获取Relative Location)【获取当前相对位置,与此同时还有Get Relative Rotation】

2.SET(变量)【Float(浮点)型变量,在左侧,如上图所示】

3.Float+Float(浮点+浮点)

双开旋转门

捡钥匙开门

1.创建一个布尔变量,作为判断是否捡了钥匙,然后添加一个branch(条件判断,分支语句),在Condition连上条件,True连入开门流程,False打印文本“你没有钥匙”(用print 打印)。
2.不同蓝图之间通信:比如一个定义在door里边的bool变量,如何在key蓝图里边修改他的值:GetAllActorsOfClass,传出某个类的数组,使用数组操作Get设置index获得对应Actor,再设置Actor下的变量(在Gate后添加get all actor ,在Actor Class选择Door_NeedKey,在Out Actors选择Get ,输出选择设置Key,打勾,意为已经捡起钥匙。);可以用来做点名系统等;注意使用顺序,先要选择好类型,再使用数组操作的Get节点,有点预编译的味道了;
3.Actor消失:Destor(捡起钥匙后自毁 destroy actor);
4..Print String(打印字符串)【做测试用的】
5..SET(变量)【Bool(布尔)类型变量,在左侧】
6.Branch(分支)【和布尔结合使用,做判断用的,若条件(就是那个布尔)为True,则执行True相关连线的命令,若为False,则执行False相关连线的命令】
7.Get All Actors Of Class(获取类的所有actor)、【把其他蓝图中的东西调过来的第一步,在Get All Actors Of Class下面Actor Class中选择你想调过来的蓝图,然后在右面Out Actors后面接上Get】
8.Get(复制)【此处的Get意思是明确刚刚调用出来的门的那个蓝图是场景中第几个相同蓝图的物体的,啊啊啊啊啊反正就是,一个蓝图写好了不是可以扔在场景好多个嘛,然后这个玩意儿就是判断是第几个的,就是万一场景一堆门,确保这把钥匙只能开第几个门的】
具体蓝图

在这里插入图片描述

小白人进入某区域后加速

完整的蓝图:

思路:两张蓝图通过蓝图通信实现效果。第一张是触发盒子的蓝图(即加速的区域),第二张是小白人的加速蓝图(即被加速的对象)。

第二张蓝图为自己在小白人的图表中新建的一张,用来专门获取小白人的速度。上方组件中的CharacterMovement为小白人的控制属性,单击后在右侧细节面板可以看到可调节的小白人的各种属性。通过添加自定义事件(Custom Event),获取到小白人的最大行走速度(Get Max Walk Speed)。

第一张蓝图中运用一个类型转换,在后面获取到了刚刚第二张蓝图中的自定义事件,即获取到了小白人最大行走速度,并可以对其参数进行修改,实现触发效果。

新的节点:

1.Cast To(类型转换为)【就是用于获取其他蓝图中的某个事件、类、变量等,使其与本蓝图中的某个东西发生联系(这个案例中就是就是触发盒子),并可在后面连的东西中更改事件内容】【2020.6.11补充:类型转换相当于一个过滤器,过滤掉其他东西,只有指定类型转换的actor才能触发后面逻辑】

2.Custom Event(添加自定义事件)【就是自己可以添加事件,然后在蓝图之间互相传数据】

蓝图通信

用于蓝图数据之间的通信,比如从一个类获取另一个类的变量,并进行一些设置;

1.Cast to选择转换的目的,转换成功从As...获得对象,可以对该对象Actor的变量等进行设置,这可以用于蓝图通信;同时Cast to有针对性,只有转换成功才有下一步。通过set设置值,get获取值
2.自定义事件:AddCustomEvent(定义一些事件,如加速,扣血等等)。
3。判断一个变量是否有效:Is Valid是一个执行节点,input Object连接待判断变量值是否正确,是否为空等;
4.通过新建变量,选择为蓝图类引用类型建立场景中某个Actor的引用,可使用带问号的IsValid判断是否有效;要使这个变量有效:1.开启睁眼;2.选中建立变量的蓝图开启细节面板;3.选中变量对用吸管,在场景中赋予变量具体值;
5.控制台命令执行Execute Console Command:ce+空格+自定义事件名可以直接进行蓝图通信(比如从蓝图Actor通信到关卡蓝图,在关卡蓝图创建自定义事件,在蓝图Actor调用);
6。ForEachLoopWithBreak,使用条件中断循环,比如触发某个事件,或者直接将后继连上break传输到Complete;
7.设置可见性Set Visibility:设置是否可见bool,但是不管是否可见碰撞依然存在;

蓝图的概念汇总

1.函数:一段可以直接或间接被调用的功能模块;可能使用return节点来做输出设置;注意纯函数,对于创建的函数节点可以在细节面板设置,纯函数没有执行流;
2.宏:用于计算,传入对应数值,套入宏进行计算;宏一般在别的蓝图里边没办法获得,是一个局部使用的,还有一种办法是新建蓝图宏库,可以实现全局调用;
3.函数内不能加流程控制;
4.放入到场景中的是类的对象,修改对象参数不会影响类本身,修改类会影响后续放入的对象;因此也就能理解变量类型部分对于对象引用和类引用的区别;
5.层级关系:Object(对象)>actor(演员,可以放到场景中的,有组件,而Object没有,因此actor中有Scene组件,表示位置坐标)>pawn(可控制角色,响应鼠标键盘可被操控,这是与actor的区别)>character(人形角色模板,行走跳跃,飞行等,有角色移动组件)
6.由于actor没有控制权,因此才有了额外采用Enable Input的开关控制,这在Pawn和Character中不是必要的,自带输入控制
7.关卡蓝图实际是actor的子类;

物体自传

一、控制物体一直自由旋转

1.搜索“AddLocalRotation”/“添加本地旋转”,此时可以看到旋转的三个轴向xyz都可设置,想要绕垂直方向旋转,可设置Z值。(因为Z值是竖直方向,旋转值是正值时,做顺时针旋转)。
2.要想持续旋转,将event Tick(事件 Tick)加入,作用:每帧都调用控制器。

二、创建布尔值(bool)控制旋转

1、在变量中创建一个变量“是否可以旋转”,将此变量拖拽到事件图表中
2、创建布尔值。按快捷键B。
一般情况下,此布尔值的默认值是不勾选的,为false
3、是否可以旋转作为布尔值条件的输入,事件Tick作为布尔值开始执行的输入。布尔值的True作为“添加本地旋转”的输入。在这里插入图片描述
三、通过分支控制另一个布尔值bool的变化
1、在蓝图中搜“添加自定义事件”,叫做控制旋转。
2、设置“是否可以旋转”这个bool值
通过分支设置,分支中的条件“Condition”l连接要改变的bool值(是否可以旋转)
如果进来的是False,转换后是True;如果进来是True,转换后是False.

在这里插入图片描述

 四、创建蓝图类的对象应用
1、知识点:蓝图类的对象引用
1.1 操作步骤:(在上述蓝图Actor之外的蓝图中,以第三人称蓝图为例)
首先添加一个变量,取名“自转物体引用”,在细节面板中修改其"变量类型",在“对象类型”模块中可找到要引用的蓝图的名字(自转BP),鼠标放在右边的小三角上可看到“对象引用”并选择,这样,就将蓝图转换成为了蓝图类的对象引用。在这里插入图片描述
1.2 设置蓝图类对象引用的值
选中此蓝图类所在的物体,即第三人称物体。在其细节面板中有个默认模块,里面就是此蓝图类对象引用,点击小三角列表查找 /或者吸管来确定对应的蓝图在这里插入图片描述
2、使用“对象引用”类型的变量
2.1 将创建蓝图类型的“自转物体引用”拖拽出来
2.2 引用蓝图类对象引用里的函数——控制旋转
2.3 设置按键(Q),按下按键后判断值的有效性,所以按键作为有效性判断的输入端。
如果有效,执行上述的函数(”控制旋转”)在这里插入图片描述
3、按键Q,即可看到蓝图自转BP中的立方体开始自转,再次按下停止转动。
Add Local Rotation(添加本地旋转)【给物体的旋转添加一个差量】
is Valid【判断变量是否有效,反正用到变量就得写这个

点名系统

点名旋转

在这里插入图片描述

1. Get all actors of class,目的是获取这个蓝图类里所有的actor(一定要先选择要获取的类,然后在获取值,否则会获取不到所想要的值)。
2.添加一个Get 去获取到具体的哪一个旋转物体进行点名,这边注意之前说过的0就是意义上的第一个
3.添加一个之前在旋转物体里写过的自定义事件名称

循环遍历旋转
在这里插入图片描述

for each loop:它的意义在于循环遍历场景中的所有该类actor(和场景中所有该类actor都通信一次),那么它连接到最后的节点功能作用在于每和其中的一个该类的actor通信一次都执行一次它里面的自定义事件,注意是一次,因为我们旋转物体的蓝图里写的是一直循环旋转所以它最终修熬过才是一直旋转。这个循环遍历等它全部执行完一遍之后就会停止了。
 在这里插入图片描述

绿色的Array Index其实就跟点名旋转中的Get是一样的功能,
Completed就是它执行完成之后就可以使用这个节点功能去做一些其他的事情(这个自行设置)

完整蓝图

random integer(随机整数)【随机生成一个整数】

解谜小游戏

 门的构建


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

首先运用一个类型转换,指定只有小白人可以触发后面的效果,(略过分支那里)用一个设置可见性来触发靠近时显示文字的效果,后面就是按键常规操作,再往后,逻辑是只要打开门了,以后再进入触发盒子也不再显示文字了,所以此处设置一个布尔,当按键以后,布尔值变为True,再往前找到那个分支,那个分支里写的是如果布尔值是False才执行,一开始设置的布尔值就是Flase,后来按键变为True以后,就不执行了,以此实现效果。

灯的构建

1.加入静态网格体 选择LAMP
2.添加聚光源组件 调整角度向上照射
3.for each loop with break 可中断循环 遍历列表中的灯是否全部被点亮 没有被点亮中断循环
4.循环执行完毕 判断是否可以开启机关 布尔值 为真则执行控制台命令
5.执行控制台命令 Execute console command
6.输入命令 ce 空格 开启机关门(关卡中自定义的事件名称)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这个蓝图分两部分,前半部分开灯的逻辑与上述开门的类似,重点和难点是后半部分乱七八糟的布尔逻辑。后半部分,首先获取此蓝图的所有actor,进行自个儿的蓝图通信,后面用一个可中断的循环去遍历数组。假设场景中有五盏灯,那么这个的逻辑就是,如果我已经开了前两盏灯,即前两盏灯的If Opened的布尔值都是True了,现在开的是第三盏灯的这个蓝图,那么首先第三盏灯的If Opened布尔值在“获取类的所有Actor”前面的“Set”处已经变成True了,循环体的遍历过程从第一盏灯开始,True,很好,分支走上面的Set,Open The Door的布尔打勾,变成True;继续遍历第二盏灯,True,很好,分支继续走上面,Open The Door的布尔还是True;第三盏灯,刚打开了,也是True,很好,Open The Door的布尔依然是True,继续!到了第四盏灯,哎嘿,还没打开过,If Opened的布尔是Flase,完了,走下面,Open The Door的布尔的勾被取消了,变成False了,不仅这样,这条线往回拐,拐回去到Break去了,循环中断,执行Completed,又连着一个判断Open The Door的布尔值得分支,是False,然后就凉凉,没法激活执行控制台命令,也就无法激活下面那张蓝图的自定义事件(开隐藏门“Open hidden door”)。只有六盏灯全打开了,才能一路循环走上面,Open The Door的布尔值一直是True,直到开心地循环遍历完整个数组,也不会被Break,然后开心地走下面Completed,分支处判断Open The Door的布尔值是True,于是乎激活了执行控制台命令,控制台又激活了下面关卡蓝图的Open hidden door的自定义事件,隐藏门才能顺利地打开!总而言之,只有所有灯都打开,才能平稳顺利执行完循环遍历数组,保证了Open The Door的布尔值始终是True,才能顺利激活控制台命令!

1.Set visibility(设置可见性)【设置物体是否可见,注意!有碰撞的模型若勾选不可见,虽然看不到模型,但是碰撞依然存在!】

2.For Each Loop with Break【循环(遍历)某个数组并可以触发中断。其中Array连接要循环的数组,Loop Body是要循环的内容,Array Element是判断循环变量,按照顺序获得取出的值?Completed表示循环结束后走的路,如果在循环的内容中触发了某条而连接到了Break中断循环,也会走Completed。】

3.Execute Console Command(执行控制台命令)【关卡蓝图间的直接通信。控制台命令输入ce+空格+关卡蓝图中自定义事件名称,可直接进行蓝图通信。】

 快捷键

1.选中控件按键盘C 可以添加注释

 

蓝图概念 

 

纯函数没有执行流如(get player controller);不修改数值,只记录或者进行计算,然后输出

宏与函数的区别:
1.函数可以在别的蓝图类中调用、获得;宏只能在这个蓝图类中本地使用,但宏库可以全局使用。
2.宏可以有多个执行引脚,但函数是固定的。

  

多人物控制权切换

MultiGate(按顺序执行一系列引脚)是Gate的加强版,有更多的执行流。reset:重置,is random:随机,loop:循环,start index:从那个下标开始。

为了视野切换有个过渡,添加 Set View Target with Blend(使用混合设置视图目标):【摄像机视角切换】,延迟(delay),possess(控制):【切换控制权】。

整体逻辑:使用MultiGate实现多个人物之间的切换,使用possess来获取切换后人物的控制权,使用Set View Target with Blend来实现切换视角的过度。首先用数字2键来控制人物的切换,然后在MultiGate节点中引出三个人物分别的控制切换,在Set View Target with Blend节点中,设置切换过度的时间为1秒,即用1秒的时间进行两个人物切换的视角方面的动画(注意!此时角色控制权仍未切换)。随后用一个和切换视角的过度时间相同的Delay节点来使前面的切换过度动画能够完整播完,然后用possess节点切换人物控制权。此处如果不用Delay节点,那么直接就会执行possess节点,那么视角将直接切换,前面的过度动画将会被直接打断。有些人手贱,在切换动画还没播完的时候就想着再按一次切换人物,那么,未防止此类问题导致程序出错,前后加入一个bool类型的变量来判断过度动画是否播完,若没播完就算再次按键也将无法进行切换。

角色上下车功能

添加一些必要的碰撞组件

在这里插入图片描述

1.box:碰撞盒子, 触发重合事件,up:碰撞的球体,上车位置,down :碰撞的球体下车位置 
还有一个类型为Pawn的变量:小白人
2.注意上下车事件都是在SeDan里,就是车子的蓝图类里写的事件

上车
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

 下车

在这里插入图片描述

在这里插入图片描述

小白人蓝图

在这里插入图片描述

注意事项

① 人物在上车之后要取消自己的碰撞,不然会出问题
② 人物在下车之要添加自己的碰撞和取消车子的碰撞,不然也可能会出现问题
③ 那个设置位置的函数,要选择相对于环境,不然也会出现问题
④ 在使用一个变量之前,要判断它是不是有效的.
⑤ 这两个事件都多次使用了自己,就是把对象赋值给实例

总结:

1.Set Actor Enable Collision(设置Actor启用碰撞)【开启或者关闭Actor的碰撞】
2.Get World Transform(获取场景变换)【获取某个东西在场景中的Transform信息】
3.Set Actor Transform(设置Actor变换)【设置Actor的Transform】
4.Attach Actor To Component(附加Actor到组件)【把Actor附加到组件,也就是说让Actor跟随组件,(或者说设立了父子集?)】【与此相对应的还有Attach Actor To Actor(附加Actor到Actor)】
5.Detach From Actor(从Actor分离)【还有Detach From Component(从组件分离)】

在这里插入图片描述

下车减速

1.Set Handbrake Input(设置手制动输入)【手刹效果的实现】
2.Set Throttle Input(设置油门输入)【1为加速,0为停止,-1为倒车】

在这里插入图片描述

更改给定的sedan事件图表

通过设置手动输入节点并打勾实现手刹的效果,接下来在后面连接设置油门输入节点,调整参数为0,实现速度最终为0的停车效果。整套节点不能放在控制后面,因为一旦切换了控制权,这套将不起作用。由于在车的预设部分同时存在设置油门输入的节点,而那里面的这个节点正是控制上车后车的加速减速行为的,所以在下车时按了F键以后两个事件图表中的该节点会冲突,那么将可能会导致车无法停下来或者就算停下来了车轮依然旋转的情况。因此在下车时,我们要将Throttle Input中的设置油门输入节点断掉。即用一个布尔变量来控制Throttle Input的启用和断开。用一个布尔值判断是否下车,下车就停止油门输入。布尔值默认为1,上车变为0,下车变为1。 

人物冲刺和瞬移,多段跳

在这里插入图片描述

设置人物速度

在这里插入图片描述

获取人物前进方向

这个主要是获取我们人物的方向,这里主要我们获取的是一个单位向量
在这里插入图片描述

计算人物瞬移位置

这个其实很简单,知道人物的方向,之后在当前的坐标(向量)上面加入位移就可以组合成一个新的位置向量。
在这里插入图片描述

 之后更新即可
在这里插入图片描述

视角移动

就是加一个过度效果,让我们的摄像头跟随。
在这里插入图片描述

 完整蓝图在这里插入图片描述

1. 疾跑:需要调出小白人的最大行走速度然后设置即可,在按下shift时疾跑,松开时回到普通速度。后面紧接着一个瞬移模块,新建一个整数变量来计数,如果按了两次shift,则激活瞬移,下面用一个延迟和一个变量设置为0来保证,如果两次shift的时间间隔太长,则将不能激活(控制住了必须连按两下)。
 2.瞬移:(快速按键瞬移(>=2):使用GetactorForwardVector获取向前向量*瞬移长度+当前位置=瞬移位置),通过时间轴控制瞬移时间,用一个向量插值来实现位置的过度。首先获取Actor位置传给插值节点的A,即获取了小白人当前位置,然后再获取Actor向前向量,这个向量数值为1,指向小白人的前方,然后给一个浮点乘法给他这个向量的值扩大,与刚刚获取的Actor位置相加,即为瞬移后的位置,把这个向量位置给插值节点的B。这样一连,再把实时变化的插值传给设置Actor位置节
3.镜头的过度:(Actor的摄像机组件视场修改可以获得不同广角下的视野)通过设置跟随摄像机的视野,再配合时间轴和插值
4.多段跳:直接从上面点开类默认值,在右侧细节面板输入jump,修改最大跳跃数即可。

 新的节点:

1.Get Actor Location(获取Actor位置)【获取Actor的位置,这个获取的是向量】
2.Set Actor Location(设置Actor位置)【设置Actor的位置,也是个向量的接口】
3.Get Actor Forward Vector(获取Actor向前向量)【获取Actor向前向量,向量值为1】
4.Set Field Of View(设置视野)【设置摄像机的视野,形象地比作近远广角等任何过度】
5.>=【判断】
6.*、+等

虚幻4蓝图各颜色代表的含义

白色——————————执行线,表示程序的执行流程
红色——————————BOOL变量
洋红——————————字符串变量
粉色——————————文本
橙色——————————Transform偏移矩阵
金色——————————Vector矢量
绿色——————————Float浮点型变量
青色——————————Integer整型变量
蓝色——————————object对象
紫色——————————旋转体数据

使用蓝图接口(相当于自建函数库,事件库)

1.接口实际就是一种函数的函数名,通过蓝图——蓝图接口创建,双击打开给函数命名;
2.所创建的函数interface输入输出可自行创建,只有同时具有输入输出才能当做函数来使用,没有输入,只有输出(或者也没有输出)只能当做事件来使用
3.切换到一个具体的蓝图类,在Classseting右边细节面板可以看到一个Interface,可添加我们创建的Interface,此时左边组件部分Interface部分只有可作为函数使用的部分,其他看作事件的只能输入搜索获得;
4.蓝图接口主要用于实现通信:因为接口可以作为一种库被不同的类包含,只要包含了就可以进行调用,实现通信,类似于一种公共函数库来使用,并且被不同对象包含之后可以产生不同的效果;

创建接口

我们直接在ContentBrowser中右击直接在Blueprints下创建Interface(接口),如下图所示

接口中添加函数

在接口中添加函数记得要点击Compile和Save。

 实现接口

接下来打开新创建的蓝图类,点击Toolbar>ClassSettings,在Interface部分点击Add添加我们刚刚创建的接口ITest,添加完之后点击Compile,效果如下图所示

拾取物品-射线检测

1.射线检测:LineTraceByChannel(由通道检测线条), 起始点(玩家摄像机世界坐标)(First Person Camera+GetWorldLocation),终点:getforwardvector获得向前向量*距离+当前位置(GetWorldLocation)=终点位置。注意Draw Debug Type表示是否可以看到射出的射线(可选项为None无,For One Farme一帧一条,For During 持续时间保留,在展开位置设置时间)。所谓Channel,在节点中有Visibility和Camare两种,要让射线检测能识别到这个碰撞到的物体,则在待检测物体细节面板碰撞部分开启对应通道,因此要把对应待检测物体相关通道设置为阻挡与射线检测通道一致,就可以进行射线检测识别了;


2.对待检测物体添加自定义响应通道Channel,并把射线检测调整到该通道就能实现阻挡检测了:在关卡编辑器界面Setting——ProjectSetting——Collision——TraceChannel添加追踪通道,默认响应设置为ignore(因为场景中所有的模型,触发盒子都会添加这个通道,只有设置为ignore才不会影响全部,只把对应待检测物体开启即可);


3.创建可以拾取的物体蓝图类:创建蓝图类Actor并赋予对应的Mesh(先选中对应的Mesh,再到蓝图AddComponent中点选,可以看到我们选中的Mesh(尤其是添加骨骼网格,就不是之前使用StaticMesh的方式)),修改其Collision中碰撞预设,选择Custom自定义,在碰撞是否开启选择第四个能够碰撞,通道追踪为阻挡开启检测;


4.骨骼网格(带动画的,洋红色)和静态网格(天青色)


5,新建蓝图接口,建立拾取,开启描边,关闭描边三个函数,不添加输出作为事件来使用;


6.在蓝图类中添加蓝图接口,事件图表调出对应事件;


7.LineTraceByChannel输出部分Out Hit可以用break节点分解开获得碰撞到的各种信息,例如被碰撞到的蓝图类Actor,

对于这个蓝图类发送消息,即触发Interface中定义的事件,此时就会给我们碰到的Actor发送这个蓝图接口定义的事件消息, 该蓝图类若要响应这个消息,前提是自身插入了这个Interface,并以事件方式实现了这个消息的逻辑;

8.骨骼网格设置碰撞:在内容浏览器点击骨骼网格文件,右键选择创建——物理资源——创建,按照默认创建出现橙色图标文件,双击点开可看到对应胶囊体,调整包围整个模型。之后双击打开骨骼网格体文件,将橙色文件对应的胶囊体物理资产附着上(physical部分physical asset添加)


9.蓝图接口的多功能性:同一个蓝图接口事件,在不同蓝图中可以实现不同的逻辑

AI的使用

1.导航网格:AI的移动范围,在放置模式下体积中有一个导航网格边界体积,把他拉到场景中形成一个线框,对其缩放形成AI移动范围,快捷键P可以切换导航网格是否显示;


2.导航网格的静态和动态设置:关卡编辑器中设置——项目设置——导航网格体——运行时——运行时生成(默认静态),采用动态的方式则实时计算,更加符合智能调整;


3.AI的随机移动:复制人物蓝图重命名,打开该蓝图删除所有蓝图节点并删除摄像机(AI不需要摄像机,也不需要控制);核心蓝图节点AI Move To:pawn设置AI对象;两种目标,一个是直接的位置,一个是跟踪的目标(playercharater),两者选其一就好;接触半径,靠近多近会停止打钩;输出部分有成功与失败两个出口;可以使用一个事件来驱动这个过程


4.GetRandom...获取可导航半径内随机点:以Ai位置为圆心,输入一个半径;


5.以事件设置定时器:连接设置好事件,修改时间,打钩循环,则事件将会在时间内循环驱动,实现连续随机移动;

 Destination和Target Actor二选一,一个去目标位置,一个去尾随某个Actor

在这里插入图片描述 AI MoveTo蓝图
Pawn:移动者
Destination:移动位置
Target Actor:跟踪移动
Acceptance Radius:停止范围
Stop On Overlap:勾选后靠近就会停止
导航网格默认静态,即可能发生新增墙壁时,AI撞墙
定时器蓝图结点:Set Timer by Event,通过event(时间一到就触发绑定的事件,可设置时间,通过勾选looping实现循环)

AI行为树

内容浏览器,右键-人工智能-黑板,右键-人工智能-行为树,右键-蓝图类-所有类-搜索AIController ,并配合之前建立的AI_BP(带AI人物的蓝图Actor,即小白人)。


AIController是AI的灵魂,指导AI操作,是一个控制器,控制ai蓝图类的对象 ;
行为树:AI的功能,行为的逻辑;
黑板:存储变量的地方;


AI_BP(小白人):一个执行者;
        1.双击黑板打开:创建变量(是否看见玩家(bool),要去的位置坐标(向量) );

        2.双击AIController:添加组件(AI感知组件AIPerception,用来感知AI周边),编译后可以在细节面板找到感知配置,添加感官的配置,如视力配置,里边有视线半径决定距离,按归属检测则要勾选中立方等。
        选择感知组件,在细节面板中下方添加事件:目标感知更新时。这个事件会传入当前视野中感知到的actor(类型是pawn和character的),对这个actor使用castto节点进行判断以进行后续操作,还有一个输出(Stimulus)刺激物,对其使用break进行展开,可以看到很多信息,比如是否成功感知到等;ai看到玩家时,successfully sensed返回true,ai看到变成看不到玩家时,返回false 。

        3.让AI使用AI控制器,或者就是将AI的灵魂赋予AI:打开AI蓝图,选择类的默认值,在Pawn下,修改AI控制器(选择自己新建的AI控制器);

        4.双击打开Ai行为树:有个Root节点,表示起始出发点,拽住下方放开可以看到一个复合节点用来创建分支的规则:(Selector)选择表示判断,(Sequence)序列表示执行顺序,则行为的基本规则如下:AI进来是否能感知到,进行选择,感知到了走左边,没感知到走右边

   
右键Sequence——添加装饰器——黑板,将黑板里边的变量弄过来,对其进行设置,选择下边一侧为已设置,一侧为未设置,表示一真一假,修改Observer aborts(管擦器中止)为Both,表示两边优先级一致,则左侧走了右侧就不能走,互斥;(行为树像是一个大脑中枢的做事逻辑) 

回到AIController,在控制器中设置黑板值,如下图  将感知成功与否的真假传入黑板,供行为树获取:

这样的话,当感知发生改变(进入视野或离开视野),开始事件,将目标为黑板的文字命名为“是否看见玩家”的值设置为true或false 。

1.在黑板中创建任务“随机找点”,创建最上面的那个,那个是父类,其余的都是它的子类,蓝图与ai蓝图类中相同


2.注意要先断掉蓝图类中的该事件,免得发生冲突
3.在左侧函数重载中选择接收执行AI(Receive Execute AI),则当这个任务被触发的时候就会执行这个事件,事件执行完成注意使用finish execute节点告知完成执行,才能开始下一次执行,否则就会一直停在那里,success打勾,表示任务结束,会重新执行当前路径(不会从根开始); 


4.此时随机找点任务做好了,把他附加到没有看到玩家的序列节点上。为什么叫做序列呢,因为这里实际可以添加多个任务,依次执行,直到最后一个结束,才会从Root开始重新来一遍,所以一定要有finish:将黑板中未设置连上该任务,这样的话若一直未设置就会一直执行随机找点,若上面不设置完成任务,它就会停在一次的随机找点任务中

5.此时最后一步,将行为树与AI_BP通过Controller进行AIController中:

到目前为止的基本逻辑是:

1.设置AIController,添加感知组件进行感知;
2.将Controller给到对应的AI_BP赋予AI灵魂;
3.AIController将感知结果传入黑板;
4.黑板作为行为树所需数据与行为树通信;
5.行为树中根据规则,执行任务;
6.在AIController中使用BeginPlay节点运行我们对应的行为树,则把行为树与AI_BP关联了起来

看到玩家后

1.添加任务,获取玩家位置,ai move to,完成执行
但这样的话,当ai跟随玩家时,若视角偏离玩家(如玩家转弯),ai就又随机找点了
为此,要在ai蓝图类移动组件中关闭"将旋转朝向运动"(使其旋转不再总是朝着运动方向,防止冲突),再在自身细节中打开“使用控制器旋转YAW”(使其旋转跟随控制器) 

设置焦距:相当于聚焦,让AI能更好的跟着你。

当没有看到玩家是要取消焦距。

AI挥拳

  1. 给AI_BP添加球形触发盒子,使用重叠与结束重叠执行打拳和结束;
  2. 打拳实际是一个动画播放,也就是说当触发盒子触发就播动画

 

 离开后,要清除定时器。

 

动画入门

控制人物的蓝图

控制摄像机的蓝图(即鼠标移动视角随着改变),yaw左右移动,picth 上下移动

 UI

 在开始界面加载图片

 Add to Player Screen:指定UI界面显示到那个玩家的屏幕上

主菜单制作

1.制作UI界面

 2.在button中写蓝图,remove from parent:从父项中移除(当点击这个按钮后,主菜单自动移除),get all actor of class:获得所有的类, set view target with blend:镜头混合,用于镜头过渡,posses:控制器(用于控制权的转换)。

3.在关卡蓝图中,创建UI,create widget:创建UI必须要用到的结点,add to viewport:将UI添加到屏幕上。Add to Player Screen:指定UI界面显示到那个玩家的屏幕上

 4.让摄像机获得控制权,点击摄像机在右边的details-pawn-auto posses playerer-player 0;显示鼠标-get player controller-set show mouse cursor(打勾)。

 5.获取玩家控制权后,鼠标应该消失。

 6.退出游戏

 使用多格式文本块

rich text block:多信息文本框

UI动画和暂停游戏

set visibility:设置UI是否可见

让UI显示,在设置为不可见。

 设置为变量,让暂停一开始不可见。

 按Q实现暂停

 显示鼠标,更改游戏模式为只能操作UI

 点继续游戏后,鼠标不可见,同时更改游戏模式为游戏模式。

 set game paused :paused(✔)暂停游戏,paused()取消暂停游戏,

 3DUI

 presss point key: 模拟鼠标左键与3DUI进行互动。

  是否和3DUI进行互动。

延迟时间执行,function name(事件名)中的事件,如下图,延长0.1秒执行全自动射击

 

 关闭延长时间执行的事件

 set time by function name(相当于开),clear time by function name(相当于关)一般要配合使用。

delay 也是延迟执行事件,但是不能循环,也不能被打断。

 多个界面切换与局域网联机

创建3个UI界面,主界面,搜索服务器界面,加入界面。

主界面(mainUI界面)

 搜索服务器界面(findserverUI界面)

 加入界面(joinUI界面)

 加入界面创建两个变量,name(服务器名字,string类型),serve(服务器信息,blueprint session result类型,表示绘画蓝图的结果(服务器端口,地图,人数等等))。
在text"服务器名字"右边-details-content-text-绑定创建的name变量。
name,server两个变量都要打开眼睛,勾选expose on spawn,让这两个变量暴露,生成UI时就可以设置信息,就能正确进行加入房间操作。

 create session:创建会话(在这里可以理解为创建房间),public connections:公共最大连接人数,use LAN:是否使用局域网。

find session:查找会话(在这即搜索房间),max results:最大查找数,与create session结合使用。results:返回查找结果(包括服务器的端口,地图等等)

MainUI界面实现蓝图

MainUI界面主要实现创建房间,打开服务器界面,退出游戏的功能,open level:选择打开level name()中的关卡(图中打开GameMap关卡),同时通过options设置为监听,remover all widgets:移除所有的UI界面,add to viewport :让UI界面显示出来。quit game:退出游戏

在Main的关卡蓝图中显示mainUI界面并显示鼠标。

clear children:清除scrollBox中的房间列表,重新进行搜索,find sessions:查找会话(在这即搜索房间),用for each loop进行遍历,将搜索到的房间信息加入(通过add child)加入到scrollBox的列表中,同时生成joinserverUI界面(create join server widget)

 当scrollBox中有房间信息时,将加载动画设置为不可见

加入房间 ,join session:加入会话(在这即是加入房间),与create session,find session搭配使用。

猜你喜欢

转载自blog.csdn.net/qq_52825422/article/details/125490721