GameplayAbilitySystem入门与实战(八):GameplayCueNotify
前言
GameplayCueNotify(GCN)
用于非逻辑层的效果,如音效,特效,相机震动等
CGN
有两个基类,如下图
GameplayCue Class |
Event | GE 类型 |
Description |
---|---|---|---|
GameplayCueNotify_Static |
Execute |
Instant or Periodic |
一般处理一次性触发的效果如打击效果 |
GameplayCueNotify_Actor |
Add or Remove |
Duration or Infinite |
此类GC 是实例化的,它们可以随着时间进行操作,直到它们被“删除”。当支持的“Duration”或“Infinite”GE 被移除或手动调用remove时,这些对于循环声音和粒子效果是很好的。它们还提供了一些选项来管理允许同时“添加”的数量,以便多个应用程序使用相同效果时只启动一次声音或粒子。 |
使用
GameplayCueNotify_Actor
时注意Auto Destroy on Remove
选项,否则后续调用add
可能不能正常工作
Gameplay Cue Manager
GameplayCueManager
会扫描指定路径的所有GameplayCueNotifies
然后加入到内存中,默认路径保存在AbilitySystemGlobals
中
1 | /** Look in these paths for GameplayCueNotifies. These are your "always loaded" set. */ |
1 | GameplayCueNotifyPaths.Add(TEXT("/Game")); |
如果需要修改路径可以修改插件内容
这里需要注意,如果是比较大型的游戏, 游戏中会有数量非常庞大的GameplayCueNotifies
,如果游戏启动的时候就加载所有,那么必然造成很多的内存浪费,如果有这个问题, 可以继承GameplayCueManager
,然后重写方法
1 | virtual bool ShouldAsyncLoadObjectLibrariesAtStart() const { return false; } |
当然我们必须在此类创建的时候需要如下修改GlobalGameplayCueManagerClass
或者GlobalGameplayCueManagerName
的值
1 | UGameplayCueManager* UAbilitySystemGlobals::GetGameplayCueManager() |
应用
CGN
可以依附与GE
,在GE
的Display
选项中添加CGN
;
新建static
类型的CGN
在蓝图类中设置GC
对应的Tag
编辑器模式下会自动扫描有引用关系的类,这个蛮好用的
如果GE
是Instant
模式,那么在GCN
中会先后调用Handle
和Excute
事件一次
如果是有持续时间的,那么Handle
会调用多次,因为Handle
本身就有EventType
类型以及其他因素, Excute
会在初始调用一次, 如果有Period
>0,那么每隔一段时间会执行Handle
和Execute
一次
这个
GC
的各个函数调用有点容易混淆,这里做一次测试测试
GA
持续3秒后结束,测试GE
的Period
设置1秒(非instant)执行顺序:
HE
:HandleExcuted
HOA
:HandleOnActive
HWA
:HandleWhileActive
HR
:HandleRemove
OA
:OnActive
OE
:OnExcute
OR
:OnRemove
WA
:WhileActive
测试逻辑大致见下图
GCN 类型 |
激活方式 | GE 持续性 |
执行顺序 | 结果 |
---|---|---|---|---|
static |
GE |
Instant |
HE->OE, | 没有调用OR |
static |
GE |
Duration=3 |
HOA->OA->HOA->OA->HWA->WA->ActiveAbility继续执行 ->HE->OE……….(HE->OE)*2….->EndAbility ->OE->HE->HR->OR->HR->OR |
ActiveAbility 执行完以后才调用第一次HE+OE, 最后EndAbility 运行以后执行一次OE+HE和两次HR+OR |
static |
GE |
Infinite |
HOA->OA->HOA->OA->HWA->WA->HE->OE……….(HE->OE)*n | 前两部分同上,没有结束, 手动remove以后同上一致 |
static |
Add |
与GE 无关 |
HOA->OA->HWA->WA…..HOR->OR. | 随GA 结束而结束,如果提前Remove 也正常调用HOR和OR |
static |
Excute |
与GE 无关 |
HE->OE | 没有调用OR,没法Remove |
Actor |
GE |
Instant |
与static 模式一致 |
|
Actor |
GE |
Duration=3 |
与static 模式一致 |
|
Actor |
GE |
Infinite |
与static 模式一致 |
|
Actor |
Add /Execute |
与GE 无关 |
与static 模式一致 |
我们可以发现static
和actor
模式的GCN
机制类似, 按照文档说明的, static
用Execute
以及适合瞬间触发的效果,Actor
用Add
和Remove
的方式用到有持续时间的效果也有一定道理;
一般瞬间的GCN
重写Excute
方法即可
持续性的看情况重写OnActive
和WhileActive
以及Remove
等
本地GCN
GCN
默认都是RPC同步的,那么对于部分的本地效果肯定是没必要的, 我们可以直接调用GameplayCueManager->HandleGameplayCue()
来执行本地GCN
1 | void UFlib_VGAS::ExecuteGameplayCueLocal(UAbilitySystemComponent* AbilityComponent, const FGameplayTag GameplayCueTag, const FGameplayCueParameters& GameplayCueParameters) |
测试
新建一个静态瞬间的GCN
,另外我们在之前的测试GE
中加入这个GCN
的标签
- 单人测试
- 双人测试
如果在生命回复中加入一个回复效果的GCN
效果, 比如下图
那么实测只会在服务端有特效, 这是因为我们StartupEffect
这种GE
效果是只在服务端应用,我们使用一般的GA
来添加GCN
效果就可以了
其他
优化
对于大量RPC
任务而言, 可以设置AbilitySystem.AlwaysConvertGESpecToGCParams 1
,这将转换GameplayEffectSpecs
到FGameplayCueParameter
结构和RPC,而不是整个FGameplayEffectSpecForRPC
。这节省了带宽,但也有较少的信息
Ability System Globals
Ability System Globals
类保存了GAS
系统的多数全局信息
4.24版本之后在程序启动之初需要对数据进行初始化,否则会引起报错甚至奔溃,可以到引擎子系统中初始化或者如ActionRPG
中使用自定义的AssetManager
类来初始化
1 | void USREngineSubsystem::Initialize(FSubsystemCollectionBase& Collection) |