Force texture load for mesh change close to camera.

I we have a character editor in our game. When we change the outfits, it is a simple skeletal mesh change on our characters skeletal mesh component. The problem is that the first time a new outfit is shown, it is blurry whilst the texture loads.

1st solution was to set bForceMipStreaming flag for the character’s mesh component. That only works for the first outfit that is set in the blueprint editor for the character. Any new skeletal meshes that we set dynamically as the player uses the UI will be blurry the first time it is shown.

2nd solution - Iterate through all possible skeletal meshes before anything is shown and call SetForceMipLevelsToBeResident(...) on their materials. This should work, but it doesn’t because the materials on the outfits don’t bHasStaticPermutationResource. I found this when stepping through the code. To get that to be true, I need static parameters (ok?)

This page (Instanced Materials in Unreal Engine | Unreal Engine 5.1 Documentation) says that “[static parameters] can only be changed from within the MaterialInstanceEditor and not from script.” But I see no way to set static parameters in the MaterialInstanceEditor.

Is there another way I should be doing things, so that I can set a SkeletalMesh on my character actor w/ textures forced to load.

Or is there another way I should be able for SetForceMipLevelsToBeResident(...) to work?



“bForceMipStreaming” will only work with static primitives, although starting at 4.13 it will also work on dynamic primitives like characters.

Otherwise, about bHasStaticPermutationResource, are you saying that UMaterialInstance::GetUsedTextures is not returning any textures? If that’s the case, then this would be a bug. If no material instances in the parent loop have StaticPermutationMaterialResources, then the base UMaterial will be used, so it should not be a problem.

About the outfits, my recommendation would be to get all used textures from the material (UMaterialInterface::GetUsedTextures) and then call UTexture2D::SetForceMipLevelsToBeResident on each of those. You could use functions like AActor::PrestreamTextures or UMeshComponent::PrestreamTextures, but that would only work if you assign the material override on the characters, and that will make the texture streaming visible unless the characters are hidden.

You can then wait for the streaming to complete with UTexture2D::WaitForStreaming, or wait for UTexture2D::UpdateStreamingStatus to return true, if you want to do that in an async way.



When calling GetUsedTextures(), ERHIFeatureLevel::Num is allowed if bAllFeatureLevels is also set to true. Otherwise, like you said, nothing will be returned. With this setup, textures from all feature levels will be returned, which is probably unrequired in your scenario. The current feature level used is stored in UWorld::FeatureLevel.

Hope this helps :slight_smile:

You are correct, static parameters shouldn’t work, and I was looking in the wrong place by trying to get them to be valid.

The issue, I think, lies within UMaterialInterface::SetForceMipLevelsToBeResident(...). This function calls GetUsedTextures(...) of MaterialInstance, but with the Feature level set to ERHIFeatureLevel::Num. That seems to be invalid for where the feature level is used (Material->GetMaterialResource(FeatureLevel, QualityLevel))

Your suggestion on calling GetUsedTextures myself is my solution for now. But I should be able to use UMaterialInterface::SetForceMipLevelsToBeResident(...) but that use of ERHIFeatureLevel::Num seems like a bug.