Skip to content

AssetGenerator: save simple assets (MaterialInstance, MPC, PhysMat, DataAsset...) after data population - 5.6.1 regression - #18

Open
UresiiZo wants to merge 1 commit into
satisfactorymodding:devfrom
UresiiZo:fix/mark-simple-assets-changed-5.6
Open

AssetGenerator: save simple assets (MaterialInstance, MPC, PhysMat, DataAsset...) after data population - 5.6.1 regression#18
UresiiZo wants to merge 1 commit into
satisfactorymodding:devfrom
UresiiZo:fix/mark-simple-assets-changed-5.6

Conversation

@UresiiZo

Copy link
Copy Markdown

Symptom

Since the UE 5.6.1 update (d665fd6) every asset handled by USimpleAssetGenerator and its subclasses
(UMaterialInstanceGenerator, UMaterialParameterCollectionGenerator, UPhysicalMaterialGenerator,
UDataAssetGenerator, UCurveBaseGenerator, ...) is written to disk without its data:

  • MI_Foundation_Concrete.uasset = 1,847 bytes, Parent = None, TextureParameterValues = []
  • MPC_Panini.uasset = 1,041 bytes (no parameters), PM_FreeLinearAngular.uasset = 1,119 bytes
  • Full Satisfactory dump (UE 5.6.1-CSS, 18,544 packages): 2,034 of 2,042 MaterialInstanceConstant packages
    were empty shells
    (file <= 2,000 bytes; the 8 others got dirtied by another generator), 10 of 12
    MaterialParameterCollection, all 25 PhysicalMaterial, all 674 FGMessage, 255 FGUserSetting,
    221 AnimMontage, 98 CurveFloat, ...

Meshes / textures / materials / blueprints are fine, so every vanilla mesh shows up grey in the editor.
No error is logged; every re-run prints MaterialInstanceConstant ... is not up to date, regenerating data
for the same assets, but the file on disk never changes (its mtime stays at the CONSTRUCTION-stage save).

Cause

d665fd6 moved the population of simple assets out of USimpleAssetGenerator::CreateAssetPackage()
(CONSTRUCTION stage, which always calls MarkAssetChanged() in UAssetTypeGenerator::ConstructAssetAndPackage)
into the new USimpleAssetGenerator::PopulateAssetWithData() (DATA_POPULATION stage). That method never calls
MarkAssetChanged(), and neither UObjectHierarchySerializer nor UPropertySerializer dirty the package.
UAssetTypeGenerator::AdvanceGenerationState() only saves when bAssetChanged is set, so:

  1. CONSTRUCTION creates the empty object and saves it (this is what ends up on disk),
  2. DATA_POPULATION deserializes Parent / parameters into memory,
  3. nothing saves it; the generator finishes and GC drops the populated object.

UMaterialInstanceGenerator::PreFinishAssetGeneration() has the same problem: it deserializes AssetUserData
in PRE_FINSHED, after the DATA_POPULATION save.

Fix

  • SimpleAssetGenerator.cpp: call MarkAssetChanged() right after PopulateSimpleAssetWithData() in PopulateAssetWithData().
  • MaterialInstanceGenerator.cpp: call MarkAssetChanged() at the end of PreFinishAssetGeneration().

Verification (real dump, UE 5.6.1-CSS, Windows, -run=AssetGenerator commandlet)

Targeted re-run of 3 floor MIs first (-ForceGeneratePackageNames, everything else blacklisted; 1.6 s):
MI_Foundation_Concrete.uasset 1,847 -> 7,702 B; editor Python read-back: Parent = MMI_FoundationSet_Concrete,
Albedo = TX_Concrete_BC, Normal = TX_Concrete_N, Masks = TX_Concrete_Relf, MaskAO = TX_Concrete_AOMasks;
MMI_FoundationSet_Concrete.Parent = MM_BakedStencil_01.

Then a full re-run over the whole dump with the fix (commandlet time 4 min 48 s, 18,347 packages generated,
no crash). Empty-shell counts (file <= 2,000 B) before -> after:

class total shells before shells after
MaterialInstanceConstant 2,042 2,034 0
FGMessage (DataAsset) 674 674 0
FGUserSetting (DataAsset) 255 255 0
AnimMontage 221 221 0
MaterialParameterCollection 12 10 4 (*)
CurveFloat 98 98 98 (*)
PhysicalMaterial 25 25 25 (*)

(*) these are just small assets: all of them were rewritten by the fixed run with a larger size, and the
editor reads their data back (e.g. PhysMat_Cement.SurfaceType = SurfaceType11, DebugColor set; MPC with
zero parameters: 0 / 12).

Cross-check from the log: 3,671 packages logged is not up to date, regenerating data; 3,661 of them now
have a rewritten file on disk
. The 10 that do not are all CurveLinearColorAtlas, which uses its own
generator (UCurveLinearColorAtlasGenerator, populated in CONSTRUCTION, so it was never a shell) and has the
same missing MarkAssetChanged() in OnExistingPackageLoaded() - left out of this PR to keep it minimal.

Editor Python read-back over all 2,042 MaterialInstanceConstant assets: Parent == None = 0. One MI
(MI_Liana_Ivy_01) has the engine default parent - that is the existing "Failed to deserialize Parent Material
... Falling back to default material" path, unrelated to this bug. A random sample of 8 MIs shows parent,
texture, scalar and vector parameters matching the dump.

Steps to reproduce (before the fix)

  1. Dump the game with AssetDumper, run -run=AssetGenerator -DumpDirectory=... on a UE 5.6.1 project.
  2. In the editor: unreal.load_asset('/Game/FactoryGame/Buildable/Building/Foundation/ConcreteSet/MI_Foundation_Concrete').get_editor_property('parent')
    -> None; file size ~1.8 KB.

Possibly related

Reports on the modding Discord (2026-05) of "followed the docs, everything in the editor is still white cubes /
grey" after generating with the 5.6 toolkit may have the same root cause (material instances empty ->
default material), though I have not verified those cases.

…ssion)

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant