Improvements to RuntimeCellTransformerISM

There are a few improvements related to RuntimeCellTransformerISM that I would like to discuss with the engine team.

There is already an Auto Flag option in the material system.

So, should RuntimeCellTransformerISM also have some corresponding handling for this case?

This would prevent rendering issues when Used with ISM has not been manually enabled, by relying on the Auto functionality to enable it automatically so that the material can render correctly.

In some relatively large projects, many materials do not have Used with ISM enabled. After those actors are processed by the transformer, their materials can end up missing.

I feel this is a fairly common issue and may be worth handling directly in RuntimeCellTransformerISM.

For this issue, I hope a solution can be provided.

Hello!

The automatic assignment of the material usage cannot work in the context of the RuntimeCellTransformers for 2 reasons. The first reason is that the assignment is processing in UMaterial::SetMaterialUsage and this method is not called by the RCT ISM. The second reason is that the material usage flag cannot be changed in PIE which is the case when the RCTs are executed.

That being said, adding the call to SetMaterialUsage would work in the case of cooking. That would emit a warning about the missing flag but the cooked data would use the right material. You can use the following workaround:

void FISMComponentDescriptor::InitComponent(UInstancedStaticMeshComponent* ISMComponent) const
{
	ISMComponent->SetStaticMesh(StaticMesh);
 
	auto GetMaterial = [ISMComponent](UMaterialInterface* MaterialInterface)
	{
		if (MaterialInterface && !MaterialInterface->IsAsset())
		{
			// If the material is equivalent to its parent, just take a reference to its parent rather than making another redundant object 
			if (UMaterialInstance* Instance = Cast<UMaterialInstance>(MaterialInterface); Instance && Instance->IsRedundant())
			{
				MaterialInterface = Instance->Parent;
			}
			else
			{
				// As override materials are normally outered to their owner component, we need to duplicate them here to make sure we don't create
				// references to actors in other levels (for packed level instances or HLOD actors).
				MaterialInterface = DuplicateMaterialInterface(*MaterialInterface, *ISMComponent);
 
				// If the MID we just duplicated has a nanite override that's also not an asset, duplicate that too
				UMaterialInstanceDynamic* OverrideMID = Cast<UMaterialInstanceDynamic>(MaterialInterface);
				UMaterialInterface* NaniteOverride = OverrideMID ? OverrideMID->GetNaniteOverride() : nullptr;
				if (NaniteOverride && !NaniteOverride->IsAsset())
				{
					OverrideMID->SetNaniteOverride(DuplicateMaterialInterface(*NaniteOverride, *ISMComponent));
				}
			}
		}
 
***		//Set the material usage for ISM. This only works in the context of cooking as SetMaterialUsage is not working in PIE.
***		if (MaterialInterface)
***		{
***			MaterialInterface->SetMaterialUsage(EMaterialUsage::MATUSAGE_InstancedStaticMeshes);
***		}
		return MaterialInterface;
	};

Regards,

Martin

Thank you very much for your explanation. We’ll try the solution you suggested.