4,巡逻状态
对于巡逻要设定几个点,敌人在巡逻状态下绕着几个点不断乱转。
在游戏窗口左侧搜素Nav Mesh Bounds Volume,拖动到游戏中,将这个立方体底部和地面相交,按p键发现相交地方会出现绿色,代表可以导航的部分,将scale放大到整个地图
在BaseEnemyCharacter中添加2个组件BillBoard命名为Waypoint1BillBoard和Waypoint2Billboard,移动到人物mesh里,将物体移动到人物两边
将两个billBoard的visible属性不勾选,不显示图表,在Construction Script中当Patrol时显示,在游戏中效果是敌人不是Patrol状态,图标隐藏,否则显示
在事件图表中获取事件begin通过GetWorldLocation获得两个billboard的坐标赋给两个变量wayPoint1和wayPoint2
在行为树中不断更新两个位置信息,在行为树文件中新建任务,该文件命名为GetWayPoint_BTT,打开,创建bool值名为WayPointSet和两个blackboardKeySelector名为WayPoint1和WayPoint2
在行为树中再添加两个坐标,将Patrol行为树分支进一步完善
运行游戏:
哈哈,居然动了,真好玩!
对于调试的时候一边运行游戏一边打开行为树可以看到当前时间点对应的运行到哪一步
5,给敌人AI添加动画
右键--->动画--->动画蓝图命名为Enemy_AinmBlueprint,重定向骨骼为新的敌人骨骼,在BaseEnemyCharacter中的mesh的Animation属性选择为Enemy的动画蓝图
找到人物奔跑行走和持枪动画,重定向骨骼,去掉兼容的骨架,选择新的敌人骨架
在Enemy_AnimBlueprint事件蓝图中获取到Enemy的动画蓝图的速度和方向
根据速度和方向创建一个二维混合动画,这个动画横轴为方向从-180到180,纵轴为速度0到500,
-180和180的上下两点都是向后走动画,90和-90上下两点为左走和右走动画,0度为向前走动画,给状态机添加idle和MoveMent两个动作,在状态机属性中Root Motion选择Root Motion from EveryThing
对于敌人转向现在是转头时突然调过来,要让他有转头的过度动作,在BaseEnemyCharacter中
选择CharacterMovement中勾选这个
选择BaseEnemyCharacter,三个方向转向都不勾选
效果如下:
5,射击状态
添加多个敌人,加入多个巡逻点,在行为树射击节点新建Task,然后move to,半径300,添加Is At Location,半径700m处就停下来
这样敌人发现我们就自动走过来了,当敌人移动过来需要让他走的很慢,新建一个任务命名为SetMoveSpeed_BTT
进入射击模式先把速度降下来,再移动
接下来给人物添加武器,在BaseEnemyCharacter中添加skeletal mesh命名为WeaponMesh,
在Construction Script使用set skeletal mesh给三种射击状态添加不同武器,Attached to Component将武器绑定到人物上
在事件图表中将不同的射击模式对应到不同的自定义事件
对于第一个开枪射击事件,通过Set Timer By Event 来重复这个自定义事件,在这个事件中通过For Loop从0到3循环,Completed就将Fire Count(整数)加一,也即Fire Count=0;Fire Count<=3;Fire Count++。
循环体中计算子弹枪口向前的向量的位置信息,使用Calculate Shotgun Fire函数,之后生成子弹计算伤害,如果3颗子弹发射完了就停顿3秒再发射,在计算子弹发射位置函数中在枪口添加了一个Arrow物体,它在枪口处指向前方向,对于开枪不能让敌人那么精准,使用Random Unit Vector in Cone来将子弹向前方向偏离一点
效果如下:
6,在射击状态下加入瞄准功能和自动转身射击
给Enemy_AnimBlueprint设置好状态机,在Blueprint Update Animation中首先设置好速度和方向传给状态机
接着找到人物和敌人的旋转向量,
让敌人旋转到角色
最后再将movement的混合动画之后连接射击偏移的混合动画
7,进一步完善行为树的射击状态
在射击模式的逻辑是这样的,进入射击状态,判断敌人和角色之间距离是不是在1100之内,如果在,走左边分支,否则右边,CheckDistanceToPlayer_BTD是下图,注意的是里面的变量PlayerCharacter和DistanceThreshold这两个变量要设为public,点成眼睛这样在行为树里面才能修改默认值,PlayerCharacter变量设为blackboard key selector类型,这里是从取得黑板中的变量值,所以采用get Blackboard value as Actor
在1100cm距离之内就一边射击一边判断CheckFireArc_BTD,这里的逻辑是这样的,如果敌人旋转到角色在85度以内就设置速度移动过来,否则转身移动过来
如果距离大于1100,就走右边分支,停止射击移动到角色旁边
8,找掩体的行为树的设计和完善
实现的目标:敌人进入Cover状态,先设置没有找到掩体状态,停止射击,寻找到最近的掩体,如果找到,移动过去,设置为找到掩体状态,判断应该躲在掩体这一侧还是另外一侧,接着调用躲掩体动画,wait几秒后开始射击,如果没有找到掩体就直接移动到角色旁边
六,HUD
1,建立不同的界面枚举
HUD文件夹里右键蓝图--->枚举,名为HUDStateEnum,列举出四种界面
右键用户界面--->控件蓝图创建四个文件命名为上面的名字,我们在3P_PlayerHUD来控制四个界面的显示,将原来该文件中的这个删去
改成这样,自定义setCurrentWidget事件调用蓝图枚举创建Widget控件并且将它用CurrentWidget保存,Add to Viewport
打开LoadingScreen Widget文件把加载页面设计好
2,将不同界面完善
在Map文件夹中新建map名为MainMenu,打开发现是黑的,点击蓝图--->关卡蓝图,这样写
打开MainMenuWidget,完善界面
触发button事件,选中每个按钮,在属性-->事件中选中onclick触发,
在HUD中有vertical Box和Horizontal Box分别是水平铺满的容器和竖直铺满的容器。用于将屏幕中的各个窗口划分。
如果想实现一个方框的效果,可以用两个border里面的border为黑色,padding为3,外面border为白色,点击back按钮可以触发remove from parent返回到主页面
对于右侧界面要想点击左侧不同button右侧显示不同的界面可以在左侧的按钮Behavior属性的Visibility中选择绑定事件,定义一个枚举类,如果枚举类为哪个按钮,触发visibility
七,保存游戏
创建SaveGameFiles目录,里面建一个Structs目录,右键Blueprint--->Structure名为GraphicsSettings_STUCT里面创建六个枚举值,分别是游戏设置里面的特效质量,材质质量,光影质量等对应的枚举变量,在创建一个SoundSettings_STRUCT的结构体新建3个浮点值保存声音大小,背景音乐大小等,再创建结构体saveControlSettings保存游戏的鼠标灵敏度等信息
创建一个类基础SaveGame类名为SettingSaveGame
在里面创建一个DoseSavedSettingsExist函数,该函数负责判断保存游戏的文件是否存在,存在就拿到该文件的引用,不存在就设置好默认的设置数据
再创建一个SaveSettings函数,保存游戏肯定要拿到保存文件的引用和文件里面的每个参数的引用
再创建一个GetSavedSettings函数取得保存文件中的参数信息
再创建一个ApplyGrahpicsSettings函数,对于不同的参数里面的不同枚举使用Execute Console Command来调用不同的指令
在SettingMenuWidget中要保存信息的时候拿到Game Instance的引用,调用Save Settings方法