蓝图开发
开关门
自动开关门
在内容浏览器中右键新建一个蓝图类
添加静态网格体组件 选取对应的模型door
添加 box collision 命名为Box 规定碰撞区域
为Box添加事件,组件重叠时触发(on component begin overlap(Box)),组件结束重叠时触发(on component end overlap(Box))
在事件图标中规定时间轴(timeline),并且在内部设置门旋转的角度和时间
获取door 为door设置相对旋转(setrelativerotation) 注意,应该设置为相对旋转,否则将以世界坐标为参考(setworldrotation)导致门旋转异常。
最后根据执行流程绘制蓝图:组件重叠时开始以时间轴逐帧播放旋转动画,结束重叠时逆向播放动画,将相对旋转设定为door的z轴

按E开关门
在自动关门的基础上添加 gate组件,利用flip flop 分别控制动画的正反播放
用E键控制gate能否执行,在组件是否重叠后 利用 启动输入(enable input) 和 禁用输入(disable input) 分别控制gate 的 open close
获取玩家控制器 来得到输入的E

鼠标开关门
在世界大纲中新建一个玩家控制类,并且启动显示鼠标,点击事件,触控事件


设置点击时触发事件

show mouse cursor 是获取玩家控制器的一个选项利用其返回值进行设置

用玩家控制器控制启动和禁用输入 并且设置启动输入时显示鼠标,禁用时不显示
最终蓝图如下:

ps:应注意碰撞盒子和模型的包含结构,否则会出现意想不到的bug
用钥匙开门

在之前按键开门的基础上新增一个变量 有无钥匙 在gate启动前用分支进行判断,如果该bool值为0则不开门。

新建一个蓝图类key 当模型重叠时获得玩家的控制器并启动输入,利用获取类的所有actor并把该类设置为 key 进行蓝图间的通信 ,将outacotr的引脚设置为get[0] (因为钥匙可能不止一把),将变量 有无钥匙 设置为 1 。然后销毁actor , 让钥匙模型消失。
文本渲染组件 静态网格体间的通信
文本渲染组件
利用文本渲染组件可以在模型上显示文本,在可视选项上调整初始时是否可见。

利用文本渲染组件可以适当的时候显示文本。比如这里我们就在人物模型与门碰撞开启门前显示文本,而开启门后消失。

这里添加一个类型转换是为了确保是玩家与门发生碰撞才开门,而不是ai 。然后通过给文本设置可视性来显示或消失文本。新建一个变量 是否开门 来记录门的状态。第一次按F,则设置为 是否开门 为 1 ,并且播放开门动画。第二次按F,则设置为 是否开门 为 0 ,并且反向播放开门动画。
静态网格体间的通信
当所有灯开启时开启机关。

添加灯光(默认不开灯),模型等组件。

添加变量 是否开灯, 是否开启机关 。
当靠近灯的时候开启文本提示,离开时消失。

和之前开门差不多,利用玩家控制器输入F ,利用Flip Flop 和设置可视性 设置灯的开关
用 获得类的所有actor,选择Light(灯光)。因为需要所有灯开时才触发机关所以需要一个循环遍历 (for each loop with break)。只要有一个灯没开就退出。遍历完所有灯都可开启就 执行控制台命令(execute)开启机关。
进入循环后判断是否开灯,若为1 就将 是否开启机关;否则将 是否开启机关为0,并且break
点击视口中的静态网格体,打开其关卡蓝图添加一个自定义事件,添加对其的一个引用设置旋转。
在执行控制台命令(execute) 用 ce 自定义事件名字(ce 开启机关门) 就可以在执行完循环后执行自定义事件。

多角色切换
创建新角色
1.直接将人物蓝图拖入场景,在右边的细节面版的posses中设置自动控制玩家为玩家0
2.在窗口->世界场景设置-›游戏模式覆盖 为thirdpersongamemode,然后在左边基础-›玩家出生点 设置玩家位置
角色切换
在场景中放置多个人物模型,用shift在世界大纲视图中选中所有的人物,选中后打开关卡蓝图,把所有人物拖拽到关卡蓝图中。
multigate 是gate的加强版,可以按次序执行所有的引脚蓝图
因为人物是pawn类所以不用在按Q前获取玩家控制器(其子类charactor也是)。 按Q后接入multigate,延迟0.2秒钟后用 control(这是 获取玩家控制器的调用 ,所以只可以在获取玩家控制器的引脚下呼出)
直接切换玩家会导致视角有割裂感,所以可以使用混合设置视图目标 setview(也是获取玩家控制器的调用)来控制视角变换。将变换目标设置为 获取玩家控制器 新的视角目标为下一个人物。blendtime设置为2秒。
最后为了关卡蓝图的美观可以将固定的流程(没有变换的输入)重叠到宏。
注意:当视角混合过程中还按了Q那么就有可能出现bug,所以需要创建一个变量 panduan 来 判断人物是否切换完成,切换过程中无法输入。
切换视角时需要将new view target 设置为下一个人物的蓝图类。否则会出现bug

利用蓝图接口通信

在内容浏览器新建蓝图以及蓝图接口

在蓝图接口中添加一个函数CanopenDoor

以事件的方式调用CanopenDoor,以蓝图编程整个开门过程

在ThirdPersonCharacter类中新建一个变量Th_door,类型为Door类型的蓝图
在ThirdPersonCharacter类中 按1就与CanopenDoor通信 ,但是现在的变量door仍是空的。所以需要在与box碰撞时把Door类中的内容传进去。也是因此需要通过类型转换与Th_door进行传输,并且将Door类自身传输过去。


这样在人物与box重叠时就与ThirdPersonCharactor进行通信,将Door类传输给了ThirdPersonCharactor中的变量Th_Door,
这是Th_Door是存在的可以通过 ?is Valid 并且与CanopenDoor通信。最后在Door类中开始调用开门的具体内容。
注意: ?is Valid 是必须要的否则会导致在Th_Door为空时无法调用而报错。
控制载具

这里就用UE4自带的载具模型。在载具的蓝图类中添加好 组件: Box 上车的碰撞盒子 ; Up上车后人物的位置 ; Down 下车后人物的位置 变量:小白人 设置为 Pawn 类型的引用 ; 下车 判断人物是否下车
调节他们的位置和大小如上图
在sedan类下创建一个自定义事件 上车

在人物类中新建一个变量 VehiclRef 设置其类型为Sedan ,并设置为公有让其他的蓝图类可以访问 此时 这个变量是空的,如果没有 ?is valid 就会报错 ,接下来调用上车的自定义事件,并且把自身传过去。
回到Sedan类
通过类型转换的方式与Vehiclr Ref 通信 并将自身设置为Vehiclr Ref,设置Vehiclr Ref需要从类型转换的引脚中拖出
触发自定义事件上车后进入Gate分支将控制权给到自身(Sedan)
变换控制权之后就可以开走载具了,但是人物模型会停留在原地。所以还需要进行一个角色位置的变换。
变换的目标设置为小白人,变换的位置设置为Up,所以用Up 获取场景变换 再 拆分变换,将新的位置 和 旋转 传到 设置actor中
但是到这里因为人物和载具都有碰撞体积,所以会出现镜头疯狂旋转的动画,因此接下来需要取消小白人的碰撞并将其附加到Up的位置
以小白人的变量引用为目标 设置actor启用碰撞 为取消 然后 附加到组件 目标为小白人 附加到的父类为 Up 所以的参数都设置为保持场景。最后设置变量 下车 为空。

下车和上车差不多但是过程反过来。
因为此时的控制器在Sedan上所以直接在这个类里输入 F 即可。 判断一下小白人是否为空,然后让小白人进行 从actor分离。
设置actor变换让小白人变换到 Down的位置,为了让视角不倾斜,我们只让Z轴进行变换
开启小白人的碰撞
把控制权重新交给小白人,小白人类型应该为pawn
但是现在还有点问题,下车视角比较僵硬; 下车后载具依然会向前滑行。
因此我们需要混合视图目标 , 他在 获取玩家控制器 的调用 set view ,将视图混合到小白人上。
在Sedan类中找到 设置油门输入 当 下车 时进入分支无法输入油门

在Sedan类中 以 Vehicle Movement 的引脚 设置手制动输入 set hand 也就是启动手刹。然后 设置油门输入 为 0



射线检测的计算方式拾取物品
射线检测的计算方式
用射线检测的计算方式检测骨架网格体,利用蓝图通信的方式按F,销毁模型。

在人物模型类当中新建 event tick (会不断得触发) .在左侧组件栏中拉出 人物的camera 获取到场景位置(get world location) 作为 由通信追踪线条 的 起始点。 再由该起始点加上当前摄像机方向上的向量(获取当前向量 get forward vecotr) * 500 个厘米 再加上原来的位置 作为 由通信追踪线条 的 终点。
选择Draw Debug Type 为 任意模式进行debug。运行即可看到由摄像机不断发出的追踪线。
利用蓝图通信与骨骼网格体通信
自定义和设置,碰撞的响应通道
想要用射线检测与物体进行通信,需要设置设置响应的通道,让该物体在此通道中被阻挡。
添加响应通道 :
在视图窗口 设置 -> 项目设置 -> 引擎 -> 碰撞 在 Trace Channels 中新建一个追踪通道 默认响应设置为 ignore , 当目标模型需要响应时才设置为响应。 这里取名为 PickUp。

实现蓝图接口通信

新建一个acotr蓝图类Pick_Up,先选中一个骨骼网格体(先选中可以快速添加),添加组件进入该类。

设置其碰撞预设为自定义(costom),将刚才设置的响应通道PickUp打开。这样射线可以阻挡该骨骼网格体
新建一个蓝图接口 PickUp_interaction ,添加PickUp函数。不要添加输出,这样可以把它作为事件调用。

在Pick_Up蓝图类中添加刚才新增的蓝图接口 PickUp_interaction ,这样可以使用在蓝图接口中的函数

在Pick_Up蓝图类中新增一个图标,以事件的方式调用Pick up ,最终要销毁自身,达到拾取物品的消失。

最后修改射线检测的 图表 。在hit选择中选中 hit actor 然后向PickUp通信,调用该事件。
AI行为树
控制器 ,行为树 , 黑板

创建AI控制器 ,行为树 , 黑板
在黑板中新建两个变量,是否看到玩家,要去的地方。

在AI蓝图中添加ai感知组件,设置AI视力配置,并且设置其下选项

在行为树中添加 选择 和 序列 。
在行为树中设置装饰为黑板。设置变量为是否看到玩家。分别修改为已设置或未设置表示看见了或没看见。
新建任务当看到玩家时进行 Seek_Player ,没看见时执行 Find_Point 。

在人物蓝图中人物运动类中将旋转朝向运动关闭

在类的默认设置中 使用控制器旋转YoW

这样AI就会一直面向玩家,不容易丢失了。
进入任务蓝图
Seek_Player就是让ai移动到玩家位置 由事件接收执行AI 的事件调用 , 设置焦距可以时ai
一直面向玩家,最后要完成执行才可以继续进入下一个事件。

Find_Point 则是随机获取可导航半径的一个点来进行移动
这里的 获取可导航半径内的随机点 参数半径 要设置 否则AI不会移动。

那么AI如何调用行为树呢?
以事件开始运行 为引脚 运行行为树
利用类型转换进行通信,当目标感知更新时把黑板中的变量 是否看到玩家 设置为布尔。这样在行为树中 是否看到玩家就是已设置的状态,可以进入Seek_player的序列了。
AI播放攻击动画
可以用 蒙太奇播放 动画
当模型开始碰撞时 执行挥拳的动画。 注意要播放蒙太奇动画需要配置插槽 ,这个插槽相当于一个标签,用于标志动画。
但是我这样一直没有成功,因为我重定向的动画让我的AI一直保持T-POSE,搞了很久都没有解决。




