|
发表于 2022-12-17 20:16:18
|
显示全部楼层
常用的Abilty和Effect
1、眩晕(Stun):
- 一般在眩晕状态时, 我们需要取消Character所有已激活的GameplayAbility,并且在整个眩晕期间,阻止新的GameplayAbility激活,以及阻止移动. The Sample Project's MeteorGameplayAbility在击中的目标上应用眩晕效果.
- 在眩晕GameplayTag添加时,可以调用AbilitySystemComponent->CancelAbilities(),取消目标活跃的GameplayAbility.
- 为了在眩晕时阻止新的GameplayAbility激活, 可以在GameplayAbility的Activation Blocked Tags GameplayTagContainer中添加眩晕的GameplayTag.
- 为了在眩晕时阻止移动, 我们可以在拥有者拥有眩晕GameplayTag时重写CharacterMovementComponent的GetMaxSpeed()函数,返回0,来阻止移动
2、奔跑(Sprint)
样例项目提供了一个如何奔跑的例子 —— 按住左Shift时跑得更快.
- CharacterMovementComponent会通过向服务器发送flag,预测性地处理奔跑. 详见GDCharacterMovementComponent.h/cpp.
- GA处理左Shift输入的响应, 并告知告知CMC开始和停止奔跑, 并且在左Shift按下时预测性地消耗耐力. 详见GA_Sprint_BP.
3、瞄准(Aim Down Sight)
样例项目处理瞄准和处理奔跑时完全一样, 但是瞄准是降低移动速度而不是提高移动速度.
详见GDCharacterMovementComponent.h/cpp是如何预测性地降低移动速度的.
详见GA_AimDownSight_BP是如何处理输入的. 瞄准时是不消耗耐力的.
4、生命偷取(Lifesteal)
我在伤害的ExecutionCalculation中实现生命偷取的功能.GameplayEffect会有一个类似Effect.CanLifesteal的GameplayTag,ExecutionCalculation会检查GameplayEffectSpec是否有Effect.CanLifesteal 的 GameplayTag, 如果Effect.CanLifesteal的GameplayTag存在,ExecutionCalculation会创建一个dynamicInstant GameplayEffect ,让该GE把同样数量的health应用到 Source'sASC.
if (SpecAssetTags.HasTag(FGameplayTag::RequestGameplayTag(FName("Effect.Damage.CanLifesteal"))))
{
float Lifesteal = Damage * LifestealPercent;
UGameplayEffect* GELifesteal = NewObject<UGameplayEffect>(GetTransientPackage(), FName(TEXT(&#34;Lifesteal&#34;)));
GELifesteal->DurationPolicy = EGameplayEffectDurationType::Instant;
int32 Idx = GELifesteal->Modifiers.Num();
GELifesteal->Modifiers.SetNum(Idx + 1);
FGameplayModifierInfo& Info = GELifesteal->Modifiers[Idx];
Info.ModifierMagnitude = FScalableFloat(Lifesteal);
Info.ModifierOp = EGameplayModOp::Additive;
Info.Attribute = UPAAttributeSetBase::GetHealthAttribute();
SourceAbilitySystemComponent->ApplyGameplayEffectToSelf(GELifesteal, 1.0f, SourceAbilitySystemComponent->MakeEffectContext());
}
5、在客户端和服务端中生成随机数
有时你需要在GameplayAbility中生成随机数用于枪支后坐力或者子弹扩散, 客户端和服务端都需要生成相同的随机数, 要做到这一点, 我们必须在GameplayAbility激活时设置相同的随机数种子, 你需要在每次激活GameplayAbility时设置随机数种子, 以防客户端错误预测激活或者它的随机数列表与服务端的不同步.
设置随机种子有两种方式:使用prediction key,或者通过事件发送。

如果你的随机偏差很小, 大多数玩家是不会注意到每次游戏的随机序列都是相同的, 那么使用Activation Prediction Key作为随机种子就应该适用于你.如果你正在做一些更复杂的事, 需要防范破解者, 那么使用Server Initiated GameplayAbility会更好, 服务端可以创建Prediction Key或者生成随机数种子来通过Event Payload 发送.
6、暴击(Critical Hits) 略
7、Non-Stacking Gameplay Effects
8、 Generate Target Data While Game is Paused
9、按钮交互系统
GAS的调试
1、在调试GAS的时候,我们关心的大概有以下几点:
- &#34;What are the values of my attributes?&#34;
- &#34;What gameplay tags do I have?&#34;
- &#34;What gameplay effects do I currently have?&#34;
- &#34;What abilities do I have granted, which ones are running, and which ones are blocked from activating?&#34;.
2、GAS 提供两种方便运行时调试的方式:showdebug abilitysystem和 hooks in theGameplayDebugger
3、UE对C++做了很多深度的优化,这使得我们调试的时候会遇到很多困难。如果我们用DebugGame Editor 的配置方案,还是不能调试变量的值,可以通过UE提供的宏,PRAGMA_DISABLE_OPTIMIZATION_ACTUAL和PRAGMA_ENABLE_OPTIMIZATION_ACTUAL 来打开和关闭优化
PRAGMA_DISABLE_OPTIMIZATION_ACTUAL
void MyClass::MyFunction(int32 MyIntParameter)
{
// My code
}
PRAGMA_ENABLE_OPTIMIZATION_ACTUAL4、showdebug abilitysystem:
在游戏中的控制台输入showdebug abilitysystem,该特性被分为三&#34;页&#34;, 三页都会显示当前拥有的GameplayTag,在控制台输入AbilitySystem.Debug.NextCategory来换页.
如下图,第一页显示了所有Attribute的CurrentValue:

第二页显示了所有被应用的 Duration 和 Infinite GameplayEffect, 它们的stacks num, GameplayEffects 带有那些GameplayTag 和 Modifier:

第三页显示了所有授予给你的GameplayAbility, 无论其是否正在运行, 无论其是否被阻止激活, 和当前正在运行的AbilityTask的状态.

你可以使用PageUp和PageDown切换Target, 页面只显示你本地控制的Character中的ASC数据, 然而, 使用AbilitySystem.Debug.NextTarget和AbilitySystem.Debug.PrevTarget可以显示其他ASC的数据, 但是不会显示调试信息的上半部分, 也不会更新绿色目标长方体, 因此无法知道当前定位的是哪个ASC, 该BUG已经被提交到https://issues.unrealengine.com/issue/UE-90437..
为了showdebug abilitysystem可以使用, 必须在GameMode中选择一个实际的HUD类, 否则就会找不到该命令并返回&#34;Unknown Command&#34;.
5、Gameplay Debugger:
GAS向Gameplay Debugger中添加了功能, 使用反引号(`)键以访问Gameplay Debugger. 按下小键盘的3键以启用Ability分类, 取决于你所拥有的插件, 分类可能是不同的. 如果你的键盘没有小键盘, 比如笔记本, 那么你可以在项目设置(Project Settings)里修改键盘绑定.
当你想要查看其他Character的GameplayTag, GameplayEffect和GameplayAbility时可以使用Gameplay Debugger, 可惜的是它不能显示Target的Attribute中的CurrentValue. 它会定位屏幕中央的任何Character, 你可以通过选择编辑器世界大纲(World Outliner)或者看向另一个不同的Character并再次按下反引号(`)键来修改Target. 当前监视的Character上方有最大的红色圆.

6、GAS日志
GAS源码中包含了大量的不同级别的日志, 默认的详细级别是Display, 其他更高的默认级别不会显示在控制台里.
为了修改某个日志分类的详细级别, 在控制台中输入:
log [category] [verbosity]例如, 为了开启ABILITY_LOG()语句, 应该在控制台中输入:
log LogAbilitySystem VeryVerbose为了恢复默认, 输入:
log LogAbilitySystem Display列出所有的日志分类, 输入:
log listGAS相关的日志分类:

GAS 的性优化
1、Ability Batching:
GameplayAbility的激活,选择性地向服务器发送TargetData,等在同一帧中的,最后可以将2-3个RPC压缩成一个RPC. 这种abilities常用于枪支的 hitscan.
2、Gameplay Cue Batching:
如果你需要同时发送很多GameplayCue, 可以考虑将其合并成一个RPC, 目标就是减少RPC数量(GameplayCue是不可靠的 NetMulticast )并尽可能减小发送的数据.
3、AbilitySystemComponent Replication Mode
默认情况下,ASC处于Full Replication模式, 这会同步所有的GameplayEffect到每个客户端(对单人游戏来说很好). 在多人游戏中, 设置玩家拥有的ASC为Mixed Replication模式, AI控制的Character为Minimal Replication模式, 这会将应用到玩家Character上的GE仅同步到该Character的拥有者, 应用到AI控制的Character上的GE永远不会同步到客户端. 无论是什么同步模式,GameplayTag仍会进行同步,GameplayCue仍会以不可靠的 NetMulticast 到所有客户端. 当所有客户端都不需要查看这些数据时, 这会减少从GE同步的网络数据.
4、 Attribute Proxy Replication
In large games with many players like Fortnite Battle Royale (FNBR), there will be a lot ofASCsliving on always-relevantPlayerStatesreplicating a lot ofAttributes. To optimize this bottleneck, Fortnite disables theASCand itsAttributeSetsfrom replicating altogether onsimulated player-controlled proxiesin thePlayerState::ReplicateSubobjects(). Autonomous proxies and AI controlledPawnsstill fully replicate according to theirReplication Mode. Instead of replicatingAttributeson theASCon the always-relevantPlayerStates, FNBR uses a replicated proxy structure on the player&#39;sPawn. WhenAttributeschange on the server&#39;sASC, they are changed on the proxy struct too. The client receives the replicatedAttributesfrom the proxy struct and pushes the changes back into its localASC. This allowsAttributereplication to use thePawn&#39;s relevancy andNetUpdateFrequency. This proxy struct also replicates a small white-listed set ofGameplayTagsin a bitmask. This optimization reduces the amount of data over the network and allows us to take advantage of pawn relevancy. AI controlledPawnshave theirASCon thePawnwhich already uses its relevancy so this optimization is not needed for them.
I’m not sure if it is still necessary with other server side optimizations that have
been done since then (Replication Graph, etc) and it is not the most maintainable pattern.Dave Ratti from Epic&#39;s answer tocommunity questions #3
5、ASC Lazy Loading (用到的时候再加载、可以减少内存)
Fortnite Battle Royale (FNBR) has a lot of damageableAActors(trees, buildings, etc) in the world, each with anASC. This can add up in memory cost. FNBR optimizes this by lazily loadingASCsonly when they&#39;re needed (when they first take damage by a player). This reduces overall memory usage since someAActorsmay never be damaged in a match. |
|