From 6aca26cc63123e9441d72660492b3a1d729e3ea5 Mon Sep 17 00:00:00 2001 From: UresiiZo Date: Wed, 19 Aug 2026 03:13:24 +0900 Subject: [PATCH] AssetGenerator: save simple assets after data population (5.6.1 regression) Since d665fd6 ("Update to UE 5.6.1") USimpleAssetGenerator populates its asset in the DATA_POPULATION stage (PopulateAssetWithData) instead of in CreateAssetPackage (CONSTRUCTION). CONSTRUCTION always calls MarkAssetChanged(), DATA_POPULATION never did, and the property serializers do not dirty the package, so AdvanceGenerationState() never saved the populated object. Every MaterialInstanceConstant, MPC, PhysicalMaterial, DataAsset, curve, ... ended up on disk as the empty CONSTRUCTION shell (MI: Parent=None, no parameters). Measured on a full Satisfactory dump: 2,034 of 2,042 MaterialInstanceConstant packages were empty shells; after this change 0 (Parent==None: 0/2042). Also mark the asset changed in UMaterialInstanceGenerator:: PreFinishAssetGeneration, which writes AssetUserData after the DATA_POPULATION save. --- .../AssetTypeGenerator/MaterialInstanceGenerator.cpp | 5 +++++ .../AssetTypeGenerator/SimpleAssetGenerator.cpp | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/AssetGenerator/Source/AssetGenerator/Private/Toolkit/AssetTypeGenerator/MaterialInstanceGenerator.cpp b/AssetGenerator/Source/AssetGenerator/Private/Toolkit/AssetTypeGenerator/MaterialInstanceGenerator.cpp index 86464fe..dac8331 100644 --- a/AssetGenerator/Source/AssetGenerator/Private/Toolkit/AssetTypeGenerator/MaterialInstanceGenerator.cpp +++ b/AssetGenerator/Source/AssetGenerator/Private/Toolkit/AssetTypeGenerator/MaterialInstanceGenerator.cpp @@ -98,6 +98,11 @@ void UMaterialInstanceGenerator::PreFinishAssetGeneration() { const TSharedPtr AssetUserDataJson = AssetObjectProperties->GetField(TEXT("AssetUserData")); GetPropertySerializer()->DeserializePropertyValue(AssetUserDataProperty, AssetUserDataJson.ToSharedRef(), AssetUserData); + + // AssetUserData is deserialized in PRE_FINSHED, after the + // DATA_POPULATION save. Without marking the asset changed the package is not re-saved and the + // AssetUserData written here is lost (IsSimpleAssetUpToDate then fails on every re-run). + MarkAssetChanged(); } void EnsureStaticSwitchNodesPresent(UMaterial* Material, const FStaticParameterSet& StaticParameters) { diff --git a/AssetGenerator/Source/AssetGenerator/Private/Toolkit/AssetTypeGenerator/SimpleAssetGenerator.cpp b/AssetGenerator/Source/AssetGenerator/Private/Toolkit/AssetTypeGenerator/SimpleAssetGenerator.cpp index e7e908a..93358b4 100644 --- a/AssetGenerator/Source/AssetGenerator/Private/Toolkit/AssetTypeGenerator/SimpleAssetGenerator.cpp +++ b/AssetGenerator/Source/AssetGenerator/Private/Toolkit/AssetTypeGenerator/SimpleAssetGenerator.cpp @@ -16,6 +16,16 @@ void USimpleAssetGenerator::PopulateAssetWithData() { UE_LOG(LogAssetGenerator, Display, TEXT("%s %s is not up to date, regenerating data"), *ExistingAssetObject->GetClass()->GetName(), *ExistingAssetObject->GetPathName()); PopulateSimpleAssetWithData(ExistingAssetObject); + + // Commit d665fd6 ("Update to UE 5.6.1") + // moved data population out of CreateAssetPackage() (CONSTRUCTION, which always marks + // the asset changed) into this DATA_POPULATION stage, but never marks the asset as + // changed here. UAssetTypeGenerator::AdvanceGenerationState only saves when + // bAssetChanged is set, and the property serializer does not dirty the package, so + // every simple asset (MaterialInstance, PhysicalMaterial, MPC, DataAsset, curves...) + // was written to disk as the empty CONSTRUCTION shell and the populated data was lost. + // Marking the asset changed makes AdvanceGenerationState save the populated package. + MarkAssetChanged(); } }