[程式] UE4 GameplayAbilityTask介绍

楼主: yekdniw (yekdniw)   2020-08-12 00:39:05
网页版
https://yekdniwue.blogspot.com/2020/08/GameplayAbilityTask.html
简介
本篇介绍的是UE4引擎的Gameplay Ability System(GAS)
中的AbilityTask系列。
不知道什么是GAS的话可以参考先前的文章
GameplayAbilities System介绍 (一)
https://yekdniwue.blogspot.com/2018/08/gameplayabilities-sytem.html
GameplayAbilities System介绍 (二)
https://yekdniwue.blogspot.com/2018/09/gameplayabilities-system.html
UE4 GameplayAbilitySystem -
GameplayEffect & GameplayCue 如何设定参数
https://yekdniwue.blogspot.com/2019/06/GameplayEffectAndCue.html
Gameplay AbilityTask介绍
AbilityTask建立了大量的范例,作为示范,
很多ASC内部的系统与其他系统的沟通都做在AbilityTask内。
而AbilityTask则是要在Gameplay Ability内串流程的时候使用,
AbilityTask节点不会出现在一般的Blueprint(BP)内
所以当了解完如何使用ASC,如何创造一个GameplayAbility,
以及GameplayEffect后。
应该先试着了解GameplayTask,可以对ASC能够做到的事情,
如何做事情有更深刻的了解。
以下是引擎提供的Tasks,这些都可以在
Engine\Plugins\Runtime\GameplayAbilities\
Source\GameplayAbilities\Private\Abilities\Tasks\
里面找到
RootMotion
ApplyRootMotion_Base
ApplyRootMotionConstantForce
ApplyRootMotionJumpForce
ApplyRootMotionMoveToActorForce
ApplyRootMotionMoveToForce
ApplyRootMotionRadialForce
MoveToLocation
NetworkSyncPoint
PlayMontageAndWait
Repeat
SpawnActor
StartAbilityState
VisualizeTargeting
Wait
WaitAbilityActivate
WaitAbilityCommit
WaitDelay
WaitGameplayEvent
WaitGameplayTag
WaitGameplayTagBase
WaitMovementModeChange
WaitOverlap
WaitTargetData
WaitVelocityChange
WaitAttribute系列
WaitAttributeChange
WaitAttributeChangeRatioThreshold
WaitAttributeChangeThreshold
WaitInput系列
WaitCancel
WaitConfirm
WaitConfirmCancel
WaitInputPress
WaitInputRelease
WaitGameplayEffect系列
WaitGameplayEffectApplied
WaitGameplayEffectApplied_Self
WaitGameplayEffectApplied_Target
WaitGameplayEffectBlockedImmunity
WaitGameplayEffectRemoved
WaitGameplayEffectStackChange
各细项说明
RootMotion
示范Ability如何透过RootMotionSource跟
Character的RootMotion系统连动。
经过实测PlayAnimMontageAndWait以及MoveToForce在
lag 200ms是有拉回现象的,但是JumpForce没有。
在UE4.25似乎有更新,有对这部份的程式码做修改,不过我还没有机会做测试。
MoveToLocation
会改SetMovementMode为Custom,无视碰撞。
感觉是个示范用的Task,想不到实际用途。
NetworkSyncPoint
用来做server/client同步的节点,总共有三种
BothWait
OnlyServer
OnlyClient
讯息处理的来回都是使用RPC。
Client 的部分会多加上prediction window,
可以用来作client prediction。
例如client先上effect或是gameplay cue,
server再apply effect。
如果要做上面说的Client prediction只有一种接法:
OnlyServerWait
OnSync后面接server与client都要
apply effect的程式码(或是BP node)。
如下图
[图]
这样接的话,执行顺序会是这样:
Client透过Input先发动Ability
Ability内执行WaitNetSync
因为Client不用等待,所以直接ApplyEffect (Client Prediction)
同时间Client也会送出RPC,并且把prediction key传过去
Server也会知道Ability发动,然后执行WaitNetSync,
等Client的RPC过来。
当收到Client的RPC过来后,Server才会通过OnSync,
然后ApplyEffect,ApplyEffect后,Server也会给一个回应,
让Client知道Server已套用这个Effect。
如果使用BothWait是不行的,因为这样Client端OnSync后,
是等到Server执行完OnSync才会执行,
这时才上Effect不仅不是Prediction,
Client还会多上一次Effect,然后再被回朔(因为Server已套用过)。
BothWait应该是要拿来处理其他事情的,不过我目前没想到使用情境。
PlayMontageAndWait
应该是最常用的节点,让角色做montage,
并且会负责处理server/client的同步,
严格来说是处理Authroity与SimulatedProxy的同步,
Autonomous要自行决定时机呼叫PlayMontageAndWait。
Repeat
就是一个timer的loop,每隔一段时间做一次,做到设定的次数就结束。
SpawnActor
从TargetDataHandle内取出第一个TargetData。
从TargetData拿HitResult,或是EndPoint作为Spawn的座标。
如果都没有,Spawn座标会是执行这个Task的OwnerActor所在位置。
StartAbilityState
让Ability进入自定义的AbilityState。
有三种方式会进入OnStateEnded
1. Ability结束
2. 手动呼叫AGameplayAbility::EndAbilityState
3. 另一个StartAbilityState启动并且勾选bEndCurrentState
AGameplayAbility::CancelAbility被呼叫的时候会进OnStateInterrupted。
VisualizeTargeting
Spawn target actor,并且呼叫TargetActor->StartTargeting。
在StartTargeting里面会让TargetActor知道可以Visualize TargetActor。
TargetActor会把视觉化的部份交给AGameplayAbilityWorldReticle做处理。
因为我的实验环境没有实作TargetActor相关的函式,
所以实际上我没有测试效果是怎么样。
Wait系列
WaitAbilityActivate
侦测AbilityActivate的事件,并且取得Ability Reference
透过GameplayTag/Query/TagRequirements来决定事件的通知。
WaitAbilityCommit
侦测AbilityCommit的事件,并且取得Ability Reference
WaitDelay
Delay一段时间
WaitGameplayEvent
非常重要的Task,GAS系统与外部系统大多都是使用Event在沟通。
通常用法是等待多个事件,再根据不同的Tag决定事件要如何处理。
WaitGameplayTag
分为Add或是Remove。
核心是靠AbilitySystemComponent(ASC)->RegisterGameplayTagEvent
RegisterGameplayTagEvent实际上对GameplayTagEventMap注册事件
GameplayTagEventMap事件只有TagCount变为0或是从0变为其他值才会发送
如果想知道TagCount变动事件要在注册的时候Type设为
EGameplayTagEventType::AnyCountChange
搜寻RegisterGameplayTagEvent可以看到范例。
WaitMovementModeChange
跟Chatacter->MovementModeChangedDelegate注册事件
呼叫SetWaitingOnAvatar,跟Ability说有个Task注册跟Avatar相关的事件。如果
AvatarActor有问题会直接结束执行这个Task的Ability。
WaitOverlap
对Avatar的PrimitiveComponent注册OnComponentHit事件
事件发生后制作TargetData,并转成Handle送出。
可能只能当作范例,直接使用不太好用。
1. 通常会知道要关注哪个Component。
2. 通常不会每个Hit都需要直接转成Handle,有可能还要做一些过滤。
WaitTargetData
负责处理一整套作
SpawnTargetActor->ConfirmTarget->产生TargetData的流程,
也会负责处理网络同步(Client给Server)
注解有说明每次都会SpawnActor,所以效率不是很好,
也提到这个Task并没有经过大量验证,
但是可以用来学习Target同步的方法。
只要不是CustomMulti的ConfirmationType,都会直接EndTask,
并且杀掉SpawnedTargetActor。 (OnDestroy)
也就是说,当Confirm后,TargetActor就删除了。除非是CustomMulti。
WaitVelocityChange
利用Tick检查ActorInfo的速度是否大于参数Magnitude,
如果有就发送事件。
WaitAttribute系列
OptionalExternalOwner让这个系列的Task可以侦测特定的角色,
不侷限于Task的拥有者。
WaitAttributeChange
侦测AttributeChange有变动的时候发送事件。
可以使用SrcTag来过滤
WaitAttributeChangeRatioThreshold
侦测两个Attribute的比例改变的时候发送事件。
由ComparsionType决定什么条件才会发送事件
WaitAttributeChangeThreshold
侦测Attribute的比例改变的时候发送事件。
由ComparsionType决定什么条件才会发送事件。
WaitInput系列
WaitCancel
侦测GenericLocalCancelCallbacks事件,
玩家触发InputAction:AbilityCancel的时候会收到。
WaitConfirm
LocalPredict的Ability如果想知道Server已Confirm这个Ability的话,
透过这个事件可以知道。
Client::ActivateAbility->Client::WaitConfirm进入等待
Server::ActivateAbility->Client收到AbilityConfirm事件发送,
Client才会通过WaitConfirm。
WaitConfirmCancel
跟WaitConfirm名字很像但意义差很大,
这边指的是玩家已经进入Targeting,
结果在等待Confirm的阶段取消的事件。
以实际上案例说明就是,玩家按了某个键会举枪(进入Targeting),
要再按另一个键A才会开枪(Confirm)。
或是按另一个键B把枪放下(ConfirmCancel)
按下A就是进WaitConfirm。
按下B就是进WaitConfirmCancel。
WaitInputPress
AbilitySystemComponent::AbilityLocalInputPressed 里面做检查
AbilitySystemComponent::BindAbilityActivationToInputComponent
里面定义按键
按键定义都在FGameplayAbilityInputBinds
GiveAbility的时候要定义Ability与inputID的关系
WaitInputRelease
AbilitySystemComponent::AbilityLocalInputReleased
其余关键与InputPress一样。
WaitGameplayEffect系列
WaitGameplayEffectApplied_Self与Target
Effect被Apply的时候会收到事件。
条件很多,除了可以用Source/Target的tag当过滤条件,
还可以用Query当过滤条件,
是不是要收到Periodic Effect事件也可以分开决定。
SourceFilter是比较少看到的过滤条件,
默认可以过滤掉不是自己,或只能是自己,
或是特定的actor等等的条件,也可以制作自定义的Filter。
WaitGameplayEffectBlockedImmunity
如果有Effect被Immunity的功能挡掉的话会收到通知。
WaitGameplayEffectRemoved
Effect被移除的时候送通知,需要传入EffectHandle。
WaitGameplayEffectStackChange
Effect堆叠数量有变动的时候送通知,需要传入EffectHandle。
常用的GameplayTasks与使用情境
这边列出我们专案常用的Task组合,
需要注意的是我们专案没有引入input与target,
所以这两个部分相关的Task都没有被列入。
PlayMontageAndWait
WaitGameplayEvent
在我们的专案大量使用到
Ability触发->
播放动作->
动作的某个时机发射子弹->
伤害判定与计算,这样的模式。
所以PlayMontageAndWait是我们的技能一定会呼叫的,
这部份算是简单易懂。
不过动作的时机要如何回到Ability,就需要靠WaitGameplayEvent了。
首先要做一个AnimNotify,
开出GameplayTag为Editable参数,
然后将Tag作为参数呼叫SendGameplayEventToActor,
这样发事件就结束了。如下图
[图]
Example of send gameplay event in animation notify.
回到Ability的BP,我们需要的是注册GameplayEvent,
所以利用WaitGameplayEvent作事件等待。
如此一来,只要Animation notify填的
gameplayTag与Ability等待事件的Tag有对上,
就能够在这个Ability得到事件的通知。
在ActionRPG的范例里面,他们直接延伸PlayMontageAndWait,
整合一事件通知与动作播放,名为PlayMontageAndWaitForEvent。
确实是很方便。如下图的Event Tags。
[图]
但是Ability并不一定只想收到动作的事件通知,
有可能会从其他系统的事件过来,
如此一来还是需要撰写WaitGameplayEvent。
最后我们为了有统一的入口,
并没有采取PlayMontageAndWaitForEvent的作法。
我们扩充的是ActionRPG中EffectContainerMap的概念,
对EffectContainerMap内将所有的Tag注册事件,
然后统一在HandleGameplayEvent里面处理。
这样不管是外部事件,动画事件,
几乎只需要看Ability的EffectContainerMap字段,
就能了解这个Ability的行为与效果。
如下图:
[图]
假设一个ContainerMap里面有两笔资料
一个EventTag 是SpawnBullet 然后Effect是给伤害
一个EventTag 是ApplyBuff 然后Effect是回血
这样企划或程式只要打开这个ability看ContainerMap的部份,
就可以知道
"嗯...这应该是会发射一个子弹给对方伤害,
然后打中可能会回血,或是发射就回血的技能"
如果想要知道回血时机,
就是透过Tag搜寻功能去查ApplyBuff是在哪里被用到就可以了。
结论
引擎虽然提供很多AbilityTask,但是我稍微看过一轮之后,
觉得AbilityTask比较像是一个教学范本。
学习者应该从里面的程式码知道AbilitySystem系统内如何沟通,
以及如何跟外部系统沟通,以及如何处理网络同步。
直接就使用内建的可能会遇到很多问题,
但是相信他们都把复杂的情况做出来了,
剩下的就是靠使用者继承这些Task并完善他们。
作者: coolrobin (泳圈)   2020-08-12 00:40:00
想说有贴到FB社团怎么没贴到PTT www
楼主: yekdniw (yekdniw)   2020-08-12 01:54:00
原订是安排周三早上发文 本篇因特殊原因先发表
作者: metallican (钢铁人)   2020-08-12 21:39:00
推推

Links booklink

Contact Us: admin [ a t ] ucptt.com