在上一节中,我们实现了通过AI行为树的修饰器,修改行为的流程控制。我们通过流程,可以区分出角色职业,使用哪一套攻击,以及在受击的情况下停止攻击状态。接下来,我们将实现通过AI行为树创建自己的任务,通过任务实现角色的技能以及攻击。
创建攻击任务类
对于AI行为树中的任务,正常我们可以通过点击创建任务,就可以创建一个任务蓝图类
如果你想了解如何创建C++的任务类,那我们先创建一个一个c++版本的了解一下。
创建C++版本的,我们需要继承BTTask_BlueprintBase基类
创建一个名为BTTask_Attack的任务类
打开代码编辑器,首先我们要覆写ExecuteTask函数,这个函数是在触发此任务时执行
UCLASS()
class AURA_API UBTTask_Attack : public UBTTask_BlueprintBase
{
GENERATED_BODY()
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
};
然后在cpp文件中实现,我们在这里不实现一些功能,因为使用内置的函数在c++中无法有很高的性能提升,但是如果有一些复杂的计算,我们可以考虑在这实现。
EBTNodeResult::Type UBTTask_Attack::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
return Super::ExecuteTask(OwnerComp, NodeMemory); //不删除是为了保证在蓝图中正常执行对应回调 ReceiveExecuteAI 和 ReceiveExecute
}
接下来,我们将在UE里创建蓝图任务类,基于我们创建的C++类,这样,也方便我们后续做扩展
打开蓝图,点击重载,选择接收执行AI
在任务完成时,一定要输出Finish Execute节点,要不然任务无法结束,如果你要结束Sequence,可以在输出时设置Success为false。
由于我们还未实现敌人的技能,所以,在这里,我们打印一下能够获取的属性,并在执行任务时,绘制一个调试球体
接着在行为树中选择,我们会发现两个Attack,不带前缀的为c++版本,它会自动将前缀去掉
我们选择蓝图版本,测试效果,如果是近战,还需要再次移动到目标附近进行攻击
我们的向目标移动的行为只是确保能够发现敌人并移动到目标附近,然后区分自身职业选择继续移动或者开始攻击。
接下来运行查看效果是否正确
处理切换行为时的敌人抖动的问题
我们会发现在向目标移动行为结束,切换到攻击时,近战还会继续向前移动,但是中间会有一个卡顿的效果,我们需要解决这个问题。
这个问题也很好解决,我们打开之前制作的混合空间动画。修改权重平滑
我们将值设置为4,那么平滑过渡时间约为0.25秒
接着运行查看效果。
增加随机位置的任务
前面我们增加了攻击的任务,在任务中,后续我们将触发攻击的释放。当角色攻击完成后,我们不希望角色傻呆呆的站在那里,而是会随机一个目标附近的位置,然后再次发起攻击。
接下来,我们将实现一个新的任务蓝图,在攻击完成后,能够随机一个可移动的点,然后移动过去。
我们先在黑板里创建一个新的键,用于存储任务随机到的位置
命名为MoveToLocation
接着选择新建任务,基于默认的蓝图基类创建一个新的任务类
需要选择一个存放任务类的位置,并命名为BTT_GoAroundTarget
在任务蓝图中,重载接收执行AI
将开始和结束的节点设置出来
创建一个新的黑板键变量,用于同步黑板上的值,记得将眼睛打开
这样我们在任务节点上可以设置绑定的键
我们再创建一个黑板键,用于获取目标
这里绑定上TargetToFollow
然后我们将Target获取使用静态函数转换成Actor,并判断它是否存在,获取它的位置
接着以目标位置为中心,获取300cm内可导航到的随机位置,并同步到黑板键上,随机位置也有可能失败,我们刚好将布尔值作为此任务是否成功失败的结果输出。
这样就完成了对整个任务的实现
现在我们将任务添加到近战行为中,先接近目标,造成一次攻击,然后等到0.5s-1.5s,然后选择一个随机位置,并移动到随机位置,如果整个流程都能顺利完成,将会重新接近目标继续执行此流程。
为了防止出错,我们在移动到随机位置增加一个time limit,它可以设置一个时间值,如果行为在此任务停留时间过于长,将会中止掉此任务,并抛出失败。
我们就设置默认的5s时间限制
设置完成后,你可以发现敌人在你身边疯狂摇摆
这一篇关于任务的创建设置就写到这里,下一篇我们将实现敌人远程攻击如果中间被阻挡自动寻找有视野的位置。