Gameplay Abilities
Network Pattern
Gameplay abilities can be activated on the owning client or the server. There are four policy types that act as a safety.
Local Predicted
The ability is activated on the owning client and sends a message to activate on the server. The server starts running the gameplay ability and sends a message back to the owning client when CommitAbility is run on the server. When the ability on the owning client receives the message it switches from predicting state to confirmed state.
Server Initiated
The ability is activated on the server first and then sends a message to activate on the owning client. When the ability activates on the owning client it will already be in Confirmed state. It will never be Predicting.
Local Only
The ability activates and runs only on the owning client.
Server Only
The ability activates and runs only on the server.
Settings
Server Respects Remote Ability Cancellation
This checkbox on the gameplay ability allows the client to cancel the gameplay ability on the server. This often has the unforeseen side effect of stopping the gameplay ability on the server before it has finished. This can often make damage effects only be applied randomly. For most gameplay abilities I uncheck this option.
Activate Ability From Event
A Gameplay Ability can be activated from a Gameplay Event Tag by adding an Ability Trigger to your Gameplay Ability. FGameplayEventData can be passed to your ability on activation and extracted in ActivateAbilityFromEvent. Normally when abilities are activated there is no way to send parameters to the ability. This is one way to get around that limitation.
IMPORTANT: When using Activate Ability from Event in BP, you MUST delete the ActivateAbility node or ActivateAbilityFromEvent will never be called. The following code snippet shows why. bHasBlueprintActivate will be true when the Gameplay Ability BP has an ActivateAbility node. bHasBlueprintActivateFromEvent will also be true when the Gameplay Ability BP has a ActivateAbilityFromEvent, but because of the "else", it will never be called.
void UGameplayAbility::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) { if (bHasBlueprintActivate) { // A Blueprinted ActivateAbility function must call CommitAbility somewhere in its execution chain. K2_ActivateAbility(); } else if (bHasBlueprintActivateFromEvent) { if (TriggerEventData) { // A Blueprinted ActivateAbility function must call CommitAbility somewhere in its execution chain. K2_ActivateAbilityFromEvent(*TriggerEventData); }