avatar
罗传月武(YueWu)@罗传月武(yuewu)
技术
UE

【GameplayAbility深入解析】之技能同步基础

logo unreal

前言

AbilitySystemComponent是UE4 Ability System插件中最核心的一个组件,后边简称ASC。

ASC中的技能同步数据基础

这一节的目的是为了理解AbilitySystem中的,每个技能从激活那一刻开始,它相关的数据是如何进行网络同步的,而且,这里的同步,不是UE4传统意义上的状态同步,而是配合PredictionKeyRpc实现的数据同步。

技能同步数据容器(缓存容器)

缓存容器

每一个激活的技能都会产生需要同步的数据,这些数据有“通用网络同步事件”、“TargetData”、“技能确认/取消”等。首先得有个地方(容器)去追踪技能上需要同步的数据。这个容器就是ASC中AbilityTargetDataMap,我称之为缓存容器

3e6ddc63-a1bc-43bc-989a-e96314236a6b.jpg

AbilityTargetDataMap中包含一个数组叫InUseData,它的元素是一个键值对,这个键值对我称之为缓存元素,键是缓存Key,值是缓存数据本身,也叫缓存体

862e2762-14cf-4210-8eb0-f9ebf94b4c7d.jpg

在一个已经激活的技能生命周期内,会有各种AbilityTask对这些数据进行同步操作。

缓存Key

缓存Key是一个由GameplayAbilitySpecHandle和PredictionKey组成的结构体,叫FGameplayAbilitySpecHandleAndPredictionKey,名字过长,所以简称为缓存Key。缓存key主要用于在缓存容器中作唯一标识。当一个技能激活后,就会作为一个新的缓存key加入缓存容器。

253feaa9-d82e-4ecd-89c0-b2c6194ab1f1.jpg

缓存体(技能同步数据缓存)

缓存体是一个结构体叫FAbilityReplicatedDataCache,也叫技能同步数据缓存

4a223133-e4de-4f55-958e-07afccbcd871.jpg

缓存体主要包含如下内容:

  • Ability的目标数据(TargetData),目标数据 常用于在客户端和服务端之间传递少量数据。作为“技能同步数据缓存”的一部分。
  • 通用网络同步事件(GenericEvents)以及回调,通用网络事件会在下方详细讲解。
  • 其他略过...

生命周期

首先缓存容器是一直存在于ASC中的一个变量。

每当ASC激活一个技能并产生任意一种网络同步操作,都会通过缓存容器的FinddOrAdd创建一个新的缓存元素,每当一个技能结束,就把自己的缓存元素从缓存容器中移除。

通用网络同步事件

这里的事件是指在一个已激活Ability的生命周期内发生的技能确认/取消,按键按下/释放,收到客户端发送的信号/收到服务端发送的信号等一系列事件。

属于缓存体(即一个技能生命周期内需要同步的数据)的一部分(叫做GenericEvents数组),用于记录这些事件及其对应的回调。

b6deea56-0e71-4603-ab89-74e549658c63.jpg

它的key就是EAbilityGenericReplicatedEvent枚举,表示事件的类型(简称EventKey),它的元素是FAbilityReplicatedData(我觉得这个名字不够具体,应该叫FAbilityReplicatedEventData,即网络同步事件的数据,简称EventPayload)。

4eaf0064-adab-414f-aa78-bb030a65fa92.jpg5a0e9109-e59f-4aa2-aa4b-ca5f9f7734aa.jpg

EventPayload里包含如下内容:

  • bTriggered,表示这个事件是否被触发了。
  • Delegate,表示这个事件的具体多播委托,在事件触发后,会被调用。

监听通用网络同步事件

通过缓存Key拿到缓存容器中对应的缓存体,再从缓存中取出GenericEvents。

  • TSharedRef 缓存体= 缓存容器.FindOrAdd(缓存key); 伪代码
  • TSharedRef CachedData = AbilityTargetDataMap.FindOrAdd(FGameplayAbilitySpecHandleAndPredictionKey(AbilityHandle, AbilityOriginalPredictionKey));

然后就可以缓存体->GenericEvents[EventKey].Delegate.Add(回调)进行事件绑定

ASC提供CallOrAddReplicatedDelegate来方便对某个事件进行绑定。

触发同步事件

ASC提供方便的接口对通用事件进行操作。

  • ServerSetReplicatedEvent(事件类型,GASpecHandle,PredictionKey),客户端告诉服务端去触发一个通用事件。
  • ClientSetReplicatedEvent(事件类型,GASpecHandle,PredictionKey),服务端告诉客户端去触发一个通用事件。

它们内部都调用了InvokeReplicatedEvent来本地触发该事件。

惯用案例

频繁用于AbilityTask中,如WaitInputReleased,WaitNetSync等。