From 030551d46e64479778f5ab7d5372c929097c9bc5 Mon Sep 17 00:00:00 2001 From: Sebastian Avena Date: Fri, 15 Apr 2022 15:27:51 +0200 Subject: [PATCH] Fix for Initialization in AcknowledgePossession in possible race condition After a lot of debugging, I found that there is a possible race condition during bad network conditions (~200ms, 5% packet loss) with 5%~10% of repro chances. If this happens, ASC will not be initialized properly and you will get `LogAbilitySystem: Warning: Can't activate LocalOnly or LocalPredicted ability %s when not local!` This happens because during AcknowledgePossession, the pawn controller is not setup yet, and during FGameplayAbilityActorInfo::InitFromActor, PlayerController will be null forever, and then, when calling UAbilitySystemComponent::InternalTryActivateAbility, bool bIsLocal = AbilityActorInfo->IsLocallyControlled() will be false I consider that OnRep_Pawn is a good place to call RefreshAbilityActorInfo, that will call FGameplayAbilityActorInfo::InitFromActor again, but the controller will be valid at that point. --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 8803d3db..4812bb77 100644 --- a/README.md +++ b/README.md @@ -361,6 +361,21 @@ void APAPlayerControllerBase::AcknowledgePossession(APawn* P) } ``` +Because possible race condition, specially with bad network conditions, the `Pawn` `PlayerController` could not be replicated yet, so I do `RefreshAbilityActorInfo()` when the `Pawn` is replicated to the `PlayerController`. + +```c++ +void APAPlayerControllerBase::OnRep_Pawn() +{ + Super::OnRep_Pawn(); + + APACharacterBase* CharacterBase = Cast(GetPawn()); + if (CharacterBase) + { + CharacterBase->GetAbilitySystemComponent()->RefreshAbilityActorInfo(); + } +} +``` + For player controlled characters where the `ASC` lives on the `PlayerState`, I typically initialize the server in the `Pawn's` `PossessedBy()` function and initialize on the client in the `Pawn's` `OnRep_PlayerState()` function. This ensures that the `PlayerState` exists on the client. ```c++