いつもお世話になっております。
表題の通りSharedStructが入れ子になっていると、子のSharedStructで保持している構造体内にあるオブジェクトがGCで流されてしまいます。
SharedStructのAddStructReferencedObjectsの処理を以下のようにすれば、GCによって流されないことを確認しています。
void FSharedStruct::AddStructReferencedObjects(class FReferenceCollector& Collector) const
{
if (auto* Struct = GetScriptStructPtr(); Struct && *Struct)
{
#if 1
Collector.AddReferencedObject(*Struct);
Collector.AddPropertyReferencesWithStructARO(*Struct, const_cast<uint8*>(GetMemory()));
#else
Collector.AddReferencedObjects(*Struct, const_cast<uint8*>(GetMemory()));
#endif
}
}
下記のAGCTestActorをレベル上に配置してPIEを開始すると同様の現象が起きます
UCLASS()
class UTestObject : public UObject
{
GENERATED_BODY()
public:
UPROPERTY()
FString String;
};
USTRUCT()
struct FObjectHolder_Base
{
GENERATED_BODY()
public:
virtual ~FObjectHolder_Base() = default;
virtual bool IsUnreachable() const
{
return true;
}
};
USTRUCT()
struct FObjectHolder_TestObject : public FObjectHolder_Base
{
GENERATED_BODY()
public:
UPROPERTY()
TObjectPtr<UTestObject> Object;
FObjectHolder_TestObject()
{
Object = NewObject<UTestObject>();
}
virtual bool IsUnreachable() const override
{
return Object->IsUnreachable();
}
};
USTRUCT()
struct FObjectHolderWrapper
{
GENERATED_BODY()
public:
UPROPERTY()
FSharedStruct Holder;
FObjectHolderWrapper()
{
Holder.InitializeAs<FObjectHolder_TestObject>();
}
bool IsUnreachable() const
{
if (const FObjectHolder_Base* HolderPtr = Holder.GetPtr<FObjectHolder_Base>())
{
return HolderPtr->IsUnreachable();
}
return true;
}
};
UCLASS()
class AGCTestActor : public AActor
{
GENERATED_BODY()
protected:
UPROPERTY()
FSharedStruct SharebleHolder;
AGCTestActor()
: Super()
{
PrimaryActorTick.bCanEverTick = true;
SharebleHolder.InitializeAs<FObjectHolderWrapper>();
}
virtual void Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (FObjectHolderWrapper* WrappedHolder = SharebleHolder.GetPtr<FObjectHolderWrapper>())
{
if (WrappedHolder->IsUnreachable())
{
UE_LOG(LogTemp, Display, TEXT("IsUnreachable"));
}
}
}
UFUNCTION(CallInEditor)
void ForceGarbageCollection()
{
GEngine->ForceGarbageCollection();
}
};
UE5.8のコードも確認しましたが、今使用しているUE5.6と同じ処理になっていたため恐らくUE5.8でも同現象は起きると思います。
お聞きしたいのは以下の2点です。
・この修正で問題ないでしょうか。
・もしこの修正に問題があるなら、どういった修正方法がよいでしょうか。
お手数をおかけしますが、お目通しいただければ幸いです。
[Attachment Removed]