FGameplayAttribute has a hash/equality mismatch. GetTypeHash is hashed by the resolved pointer. The equality operator compares the stored path strings in TFieldPath::UEOpEquals.
When a CoreRedirect renames an attribute, two UGameplayEffect assets referencing the same property - one saved before the rename, one saved after - deserialize into FGameplayAttribute instances whose TFieldPath::Path arrays differ: [“OldName”] vs [“NewName”].
Both of those attributes resolve to the same FProperty*. However, a TMap<FGameplayAttribute, …> will create a duplicate entry instead of resolving to the same one. FActiveGameplayEffectsContainer::AttributeValueChangeDelegates is an example where this is problematic. A broadcast against the delegate drops anything registered with Path = [“OldName”].
UE 5.7 handles such discrepencies in FGameplayAttribute::PostSerialize:
// Once struct is loaded, check if redirectors apply to the imported attribute field path
const FString PathName = Attribute.ToString();
const FString RedirectedPathName = FFieldPathProperty::RedirectFieldPathName(PathName);
if (!RedirectedPathName.Equals(PathName))
{
// If the path got redirected, attempt to resolve the new property
...
}
However, UE 5.8 resolves Attribute.ToString() correctly to the redirected name even though the underlying path does not match in the equality operator. This seems to be from an addition to FFieldPath::TryToResolvePath:
Result = FindFProperty<FField>(Owner, Path[PathIndex]);
if (!Result)
{
const FName RedirectedName = FProperty::FindRedirectedPropertyName(Owner, Path[PathIndex]);
if (!RedirectedName.IsNone())
{
Result = FindFProperty<FField>(Owner, RedirectedName);
}
}
PathIndex--;
So in 5.8, stale references to an attribute in an asset no longer update to the correct path as part of PostSerialize.
Can you advise on the proper intended fix? I see the following paths:
- Update FGameplayAttribute operator== to compare the resolved attribute instead of relying on FFieldPath equality? Eg Attribute.Get() == Other.Attribute.Get() instead of Attribute == Other.Attribute
- Update FFieldPath equality to account for the resolution redirecting flow?
- Update FGameplayAttribute PostSerialize to detect staleness some other way
[Attachment Removed]