TargetLock功能实现
type
status
date
slug
summary
tags
category
icon
password
设计思路
是一个可切换的能力->独立的输入策略
锁定能力的实现
- 在Level中检索待锁定的目标
- 在特定位置绘制锁定UI
- 逐帧更新UI位置和主角朝向
- 切换目标
Toggleable Ability
首先,这是一个Toggleable Ability,可切换的能力,使用相同的输入我们应该能打开和关闭此能力,因此要有独立的输入策略
实现
这个Ability继承自WarriorHeroAbility,HeroGameplayAbility_TargetLock从UGameplayAbility重写两个函数
ActivateAbility
EndAbility
添加相应的GameplayTag(Input的,Ability的,Status的)
GA蓝图GA_Hero_TargetLock继承自HeroGameplayAbility_TargetLock
GA中,Ability Tags是Player.Ability.TargetLock
Activation Owned Tags是Status中的
Instancing Policy是Per Execution
修改WarriorAbilitySystemComponent中的逻辑OnAbilityInputPressed
如果传入的InputTag是Toggleable的,就得检查这个能力的AbilitySpec是否是Active的,是的话就取消这个能力,不是的话就激活这个能力
绑定输入按键,并将这个能力赋予为武器的默认能力
得到Level中有效的待锁定目标
在C++类中定义一个私有成员函数TryLockOnTarget(),在ActivateAbility时调用
另一个私有成员函数是GetAvailableActorsToLock(),在TryLockOnTarget调用,这个函数使用KismetSystemLibrary中的BoxTraceMultiForObjects来获得目标(在 3D 空间中投射一个轴对齐或旋转的盒体(Box),检测与盒体碰撞的 多个对象(如 Actor、组件))以主角为box中心,生成一个指定长宽高的box,将碰撞到的非主角的角色加入一个数组
在尝试锁定时,如果候选目标数组为空,需要把能力关闭(调用父类的取消能力函数),并用另一个函数来做清理工作,把候选目标数组清空,把当前锁定目标的指针置空
接下来实现从候选目标中选定一个最近的目标(借助UE已经实现的FindNearestActor来实现,抽空看看怎么实现的)
尝试锁定时如果数组不为空,需拿到最近的目标,保存在一个成员中即可,若该目标无效,则取消能力
得到这组目标后从中选择一个锁定
绘制与更新锁定UI
每帧都要更新这个UI的位置
实现
在UE中创建一个继承自WarriorWidgetBase的WBP,设置好外观,在HeroGameplayAbility_TargetLock类中添加一个成员指向这个UI
使用AddToViewPort将这个UI绘制出来
Clean Up需要管理这个UI的删除(RemoveFromParent(),管理UIsize的重置)
位置,可以用当前锁定的目标的位置来设置(Widget Layout Library中的工具实现3D向量到2D向量的映射ProjectWorldLocationToWidgetPosition),在绘制之后直接设置位置
但是大小需要在cpp中被访问到,从而设置正确的大小,需要从WidgetTree中检索,设置大小只需绘制后设置一次,因此要检测设置的大小如果是默认的2D向量0,0再设置
逐帧更新UI位置和主角的朝向
自定义一个AbilityTask:从AbilityTask继承出一个类,用来处理逐帧的任务
要确保类的构造函数中,设置bTickingTask为true
重写TickTask(GameplayTask中定义,AbilityTask是GameplayTask的子类)这个函数,在TickTask中广播一个委托OnAbilityTaskTick.Broadcast(Deltatime)(广播前要确保ShouldBroadcastAbilityTaskDelegates返回true,如果是false就EndTask)
在TargetLockAbility类中实现一个OnTargetLockTick,每帧实现如下流程:
检测当前锁定的目标是否有效或有dead的tag,或主角死了,是则取消锁定能力
否则调用设置UI位置的函数
检测当前是否需要调整主角朝向(检测是否有翻滚或格挡tag)
调库Kismet的FindLookAtLocation得到Rotator LookAtRot,根据这个去调整Controller和主角的朝向(SetControlRotation, SetActorRotation)
切换动画姿势
大部分是UE编辑器里的操作,不展开
切换目标
Input Callbacks
通知切换目标,处理切换目标
Tags里添加两个方向的switchtag,为Tags绑定回调函数 触发 完成
捕获到鼠标移动,通知锁定目标的能力,发送一个Gameplay事件给这个能力,收到后处理切换目标的操作
具体切换方式是维护两个数组,数组元素为Actor*,分别代表主角左侧的敌人和主角右侧的敌人,收到切换目标的输入时,对所有候选锁定目标进行筛选,逐目标计算其在主角的左侧还是右侧,并添加到对应的数组中,计算左侧还是右侧是根据两个向量计算而来,设当前锁定的敌人的位置为点T,主角位置为点O,当前遍历到的候选锁定目标位置为点P,则计算向量Result = OT×OP,Result的Z分量为正,则在右侧,反之在左侧
从对应方向的数组中得到一个最近的目标去锁定,如果未得到有效目标就不进行目标切换(对应方向的目标数组为空)
Prev
使用远程服务器跑深度学习代码时的一些心得
Next
这天夜里
Loading...