Hello,
I’ve encountered an issue with shared fragments that contain a member variable of type FInstancedStruct. It appears that UE::StructUtils::GetStructInstanceCrc32() does not correctly compute the CRC hash for such fragments—changes to the FInstancedStruct member do not affect the resulting hash value.
As a result, when creating a shared fragment in a trait using EntityManager.GetOrCreateConstSharedFragment(), only a single entry may be generated, even if multiple Mass configs exist that differ solely in the FInstancedStruct member variable.
The issue can be reproduced using the code below and creating few mass configs with different TestVar. Additionally, I’ve attached a repro project demonstrating the problem. It contains two mass configs with different FInstancedStruct member values, yet both produce the same CRC hash. This can be observed in the logs at BeginPlay.
Can you confirm whether this behavior is expected, and if not, what would be the recommended approach to handle this case?
Best regards,
Wiktor
USTRUCT(BlueprintType)
struct FInstancedStructBase
{
GENERATED_BODY()
virtual ~FInstancedStructBase(){}
UPROPERTY(EditAnywhere)
FName Name;
};
USTRUCT(BlueprintType)
struct FInstancedStructBool : public FInstancedStructBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere)
bool Val;
};
USTRUCT(BlueprintType)
struct FInstancedStructFloat : public FInstancedStructBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere)
float Val;
};
USTRUCT()
struct FTestConstSharedFragment : public FMassConstSharedFragment
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, meta = (BaseStruct = "/Script/ArchTest.InstancedStructBase"))
FInstancedStruct TestVar;
UPROPERTY(EditAnywhere)
int32 TestInt = 0;
};
UCLASS(meta = (DisplayName = "Test Trait"))
class UTestTrait : public UMassEntityTraitBase
{
GENERATED_BODY()
public:
virtual void BuildTemplate(FMassEntityTemplateBuildContext& BuildContext, const UWorld& World) const override;
UPROPERTY(EditAnywhere)
FTestConstSharedFragment Params;
};
void UTestTrait::BuildTemplate(FMassEntityTemplateBuildContext& BuildContext, const UWorld& World) const
{
FMassEntityManager& EntityManager = UE::Mass::Utils::GetEntityManagerChecked(World);
const FConstSharedStruct ParametersFragment = EntityManager.GetOrCreateConstSharedFragment(Params);
UE_LOG(LogTemp, Error, TEXT("--------"))
const uint32 Hash = UE::StructUtils::GetStructInstanceCrc32(FConstStructView::Make(Params));
UE_LOG(LogTemp, Error, TEXT("Hash: %d"), Hash)
UE_LOG(LogTemp, Error, TEXT("--------"))
}
[Attachment Removed]