前言
AbilitySystemComponent是UE4 Ability System插件中最核心的一个组件,后边简称ASC。
ASC中的技能同步数据基础
这一节的目的是为了理解AbilitySystem中的,每个技能从激活那一刻开始,它相关的数据是如何进行网络同步的,而且,这里的同步,不是UE4传统意义上的状态同步,而是配合PredictionKey和Rpc实现的数据同步。
技能同步数据容器(缓存容器)
缓存容器
每一个激活的技能都会产生需要同步的数据,这些数据有“通用网络同步事件”、“TargetData”、“技能确认/取消”等。首先得有个地方(容器)去追踪技能上需要同步的数据。这个容器就是ASC中AbilityTargetDataMap,我称之为缓存容器。

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

在一个已经激活的技能生命周期内,会有各种AbilityTask对这些数据进行同步操作。
缓存Key
缓存Key是一个由GameplayAbilitySpecHandle和PredictionKey组成的结构体,叫FGameplayAbilitySpecHandleAndPredictionKey,名字过长,所以简称为缓存Key。缓存key主要用于在缓存容器中作唯一标识。当一个技能激活后,就会作为一个新的缓存key加入缓存容器。

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

缓存体主要包含如下内容:
- Ability的目标数据(TargetData),目标数据 常用于在客户端和服务端之间传递少量数据。作为“技能同步数据缓存”的一部分。
- 通用网络同步事件(GenericEvents)以及回调,通用网络事件会在下方详细讲解。
- 其他略过...
生命周期
首先缓存容器是一直存在于ASC中的一个变量。
每当ASC激活一个技能并产生任意一种网络同步操作,都会通过缓存容器的FinddOrAdd创建一个新的缓存元素,每当一个技能结束,就把自己的缓存元素从缓存容器中移除。
通用网络同步事件
这里的事件是指在一个已激活Ability的生命周期内发生的技能确认/取消,按键按下/释放,收到客户端发送的信号/收到服务端发送的信号等一系列事件。
属于缓存体(即一个技能生命周期内需要同步的数据)的一部分(叫做GenericEvents数组),用于记录这些事件及其对应的回调。

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


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等。