In our project, we write a custom AbilityTimerManager to replace the default TimerManager. Change some GameEffect coed, an example is below.
/*
FTimerManager& TimerManager = Owner->GetWorld()->GetTimerManager();
FTimerDelegate Delegate = FTimerDelegate::CreateUObject(Owner, &UAbilitySystemComponent::CheckDurationExpired, AppliedActiveGE->Handle);
TimerManager.SetTimer(AppliedActiveGE->DurationHandle, Delegate, FinalDuration, false);
if (!ensureMsgf(AppliedActiveGE->DurationHandle.IsValid(), TEXT("Invalid Duration Handle after attempting to set duration for GE %s @ %.2f"),
*AppliedActiveGE->GetDebugString(), FinalDuration))
{
// Force this off next frame
TimerManager.SetTimerForNextTick(Delegate);
}
*/
auto& TimerManager = *UAbilitySystemGlobals::Get().GetTimerManager();
FTimerDelegate Delegate = FTimerDelegate::CreateUObject(Owner, &UAbilitySystemComponent::CheckDurationExpired, AppliedActiveGE->Handle);
TimerManager.SetAbilityTimer(Owner, AppliedActiveGE->DurationHandle, Delegate, FinalDuration, false);
if (!ensureMsgf(AppliedActiveGE->DurationHandle.IsValid(), TEXT("Invalid Duration Handle after attempting to set duration for GE %s @ %.2f"),
*AppliedActiveGE->GetDebugString(), FinalDuration))
{
// Force this off next frame
TimerManager.SetAbilityTimerForNextTick(Delegate);
}
Then I can control the timer manually.
void UGameBlueprintFunctionLibrary::TickAbilityTurn(UAbilitySystemComponent* source, int delta)
{
auto timerManager = GetTimerManager();
if(timerManager == nullptr)
{
return;
}
timerManager->TickTurn(source, delta);
}