I’ve been working on a tool that manages the structure of my Unreal Engine content and have ran into a bit of trouble with copying assets. After copying the assets Unreal Engine doesn’t release the system resources. It’s frustrating and can lead to a system crash because in Unreal words it will “AssetCompile memory estimate is greater than available, but we’re running it [{TaskName}] anyway!”. Anyways I’ve provided the code down below and would appreciate any suggestions.
void AssetToolsCopyPackages(const TArray<FName>& Packages, const FString& Destination)
{
IAssetTools& AssetTools = IAssetTools::Get();
TMap<FString, FString> SourceAndDestPackages;
for (const FName& Package : Packages)
{
const FString PackageName = Package.ToString();
const FString AssetName = FPackageName::GetLongPackageAssetName(PackageName);
const FString DestinationPackagePath = Destination + AssetName;
SourceAndDestPackages.Add(Package.ToString(), DestinationPackagePath);
}
FDuplicatedObjects DuplicatedObjects;
AssetTools.AdvancedCopyPackages(SourceAndDestPackages, true, true, &DuplicatedObjects);
for (TMap<TSoftObjectPtr<UObject>, TSoftObjectPtr<UObject>>& DuplicatedObjectMap : DuplicatedObjects)
{
for (TPair<TSoftObjectPtr<UObject>, TSoftObjectPtr<UObject>>& ObjectPair : DuplicatedObjectMap)
{
if (ObjectPair.Value.IsValid())
{
UE_LOG(LogTemp, Warning, TEXT("Copied object is live"));
UObject* CopiedObject = ObjectPair.Value.Get();
CopiedObject->ClearFlags(RF_Standalone);
CopiedObject->MarkAsGarbage();
ObjectPair.Value.Reset();
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Copied object is not valid"));
}
}
}
if (GEngine)
{
GEngine->ForceGarbageCollection(true);
}
}
bool CopyTextures(TArray<FStaticMaterial>& StaticMaterials, const FString& Destination)
{
TArray<FName> Packages;
for (int32 i = 0; i < StaticMaterials.Num(); i++)
{
TObjectPtr<UMaterialInterface> MaterialInterfacePtr = StaticMaterials[i].MaterialInterface;
UMaterialInterface* MaterialInterface = MaterialInterfacePtr.Get();
if (!MaterialInterface)
{
UE_LOG(LogTemp, Warning, TEXT("The material interface was null"));
return false;
}
UMaterialInstanceConstant* MaterialConstant = Cast<UMaterialInstanceConstant>(MaterialInterface);
if (!MaterialConstant)
{
UE_LOG(LogTemp, Warning, TEXT("The material constant was null. Must be a material instance"));
return false;
}
for (int32 t = 0; t < MaterialConstant->TextureParameterValues.Num(); t++)
{
UTexture* Texture = MaterialConstant->TextureParameterValues[t].ParameterValue.Get();
if (!Texture)
{
UE_LOG(LogTemp, Warning, TEXT("Failed to get texture for material instance %s"), *MaterialConstant->GetName());
return false;
}
Packages.Add(Texture->GetOutermost()->GetFName());
}
}
AssetToolsCopyPackages(Packages, Destination);
return true;
}