When I run with the commented code and comment out the red code, it doesn’t freeze
You are removing elements from the map while iterating through it, which is not allowed
if you want to do that, you can do that with an iterator instead of a for:
for (auto It = ActiveEffectHandles.CreateIterator(); It; ++It)
{
if (TargetASC == It.Value())
{
TargetASC->RemoveActiveGameplayEffect(It.Key(), 1);
It.RemoveCurrent();
}
}
To diagnose why the FindAndRemoveChecked method is causing lag, let’s analyze the code and consider potential performance bottlenecks:
for (auto HandlePair : ActiveEffectHandles) {
if (TargetASC == HandlePair.Value) {
TargetASC->RemoveActiveGameplayEffect(HandlePair.Key, 1);
ActiveEffectHandles.FindAndRemoveChecked(HandlePair.Key);
}
}
Potential Issues
-
Loop Overhead:
- If
ActiveEffectHandlesis a large collection, iterating over it can be time-consuming. Each iteration involves checkingTargetASC == HandlePair.Valueand callingRemoveActiveGameplayEffect.
- If
-
Frequent Removal Operations:
- The
FindAndRemoveCheckedmethod is likely performing a search to findHandlePair.Keybefore removing it. IfActiveEffectHandlesis implemented as a list or array, this operation could beO(n)in complexity, making the overall loop potentiallyO(n^2)for large datasets.
- The
-
RemoveActiveGameplayEffect Overhead:
- The call to
RemoveActiveGameplayEffectcould be complex, involving significant processing, especially if it involves additional searches, updates, or events.
- The call to
Performance Improvement Suggestions
-
Use Efficient Data Structures:
- Ensure that
ActiveEffectHandlesuses a data structure with efficient removal operations, such as a hash map or unordered set, which can provide averageO(1)removal time.
- Ensure that
-
Batch Removal:
- Instead of removing elements inside the loop, collect the keys to be removed and perform batch removal after the loop. This can minimize the performance impact of frequent removals:
TArray<FActiveGameplayEffectHandle> HandlesToRemove; for (auto HandlePair : ActiveEffectHandles) { if (TargetASC == HandlePair.Value) { TargetASC->RemoveActiveGameplayEffect(HandlePair.Key, 1); HandlesToRemove.Add(HandlePair.Key); } } for (auto& Handle : HandlesToRemove) { ActiveEffectHandles.FindAndRemoveChecked(Handle); } -
Profile and Optimize:
- Use profiling tools to measure the exact time spent in each part of the code. Identify the most time-consuming operations and focus optimization efforts there.
-
Optimize Conditional Checks:
- If possible, optimize the condition
TargetASC == HandlePair.Valueto reduce the time spent on comparisons.
- If possible, optimize the condition
-
Reduce Complexity in RemoveActiveGameplayEffect:
- Investigate the
RemoveActiveGameplayEffectmethod to ensure it is optimized and not doing unnecessary work.
- Investigate the
Example of a Potential Optimization
Here’s how you might refactor the code to minimize the performance impact:
TArray<FActiveGameplayEffectHandle> HandlesToRemove;
HandlesToRemove.Reserve(ActiveEffectHandles.Num()); // Preallocate memory to avoid reallocation
for (auto HandlePair : ActiveEffectHandles) {
if (TargetASC == HandlePair.Value) {
TargetASC->RemoveActiveGameplayEffect(HandlePair.Key, 1);
HandlesToRemove.Add(HandlePair.Key);
}
}
for (auto& Handle : HandlesToRemove) {
ActiveEffectHandles.FindAndRemoveChecked(Handle);
}
In this refactored version:
- We collect all handles to remove in a separate array.
- After the loop, we remove all collected handles in one go, reducing the overhead of frequent removals.
By applying these strategies, you should be able to mitigate the lag caused by the FindAndRemoveChecked method.
Thanks for your reply,It’s very useful.
Thanks for your anwsers,I solved this problem.
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.

