Hello,
Its been a few days that i’m stuck on a “weird” issue.
For context, my inventory system uses a single UObject
type: UPGItem
.
This class contains data such as Instanced Structs, used as fragments to make modular items.
For each item those fragments are defined in a Data Asset, and feed to the UPGItem on creation (at this point the fragments are holded in the Item).
I’ve been using that with classes and static meshs the past weeks and got no issues.
Example:
But now, i was testing my equipment system (thats uses the same UPGItem
class) and ran into an issue: when i get a specific fragment holded in my item, the ptr is “invalid”.
It passes the IsValid
check, but after that when I use the ptr i get a exception. When i use IsValidLowLevel
, it fails.
I encountered this issue with UMaterialInterface
and TSubclassOf<UGameplayEffect>
.
Here is the variable where the instanced structs are saved in UPGItem
UPROPERTY(Replicated) TArray<TInstancedStruct<FPGBaseItemFragment>> Fragments;
Here is the code of the struct holding the UMaterialInterface
USTRUCT(BlueprintType)
struct FPGCoreEquipmentItemFragment : public FPGBaseItemFragment
{
GENERATED_BODY();
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly) UMaterialInterface* TempMaterial;
};
How i get it:
const FPGCoreEquipmentItemFragment* FoundCoreEquipmentItemFragment = CurrentEquippedItem->FindFragment<FPGCoreEquipmentItemFragment>();
the inside of FindFragment
(in case it matters):
template <std::derived_from<FPGBaseItemFragment> T>
const T* FindFragment() const
{
for (auto Fragment : Fragments)
{
if (Fragment.IsValid())
{
if (const T* Frag = Fragment.GetPtr<T>())
{
return Frag;
}
}
}
return nullptr;
}
How i get the material:
UMaterialInterface* Mat = FoundCoreEquipmentItemFragment->TempMaterial;
And finally, how I use it:
if (IsValid(SkeletalMeshComponent) && Mat->IsValidLowLevel()) // IsValidLowLevel will always fail
{
SkeletalMeshComponent->SetMaterial(0, Mat);
}
if (IsValid(SkeletalMeshComponent) && IsValid(Mat)) // IsValid would pass but encounter exception
{
SkeletalMeshComponent->SetMaterial(0, Mat);
}
Here is how it looks like inside the Data Asset:
And for the issue with the Gameplay Effects, in this 2 entry array, the first is always valid and he second not when getting it in c++