Applying a texture as texture parameter to a dynamically loaded material

I made a system in order to load pak files at runtime and it works fine : I create meshes, materials and textures. I can apply materials to meshes. Only one thing still doesn’t work : Applying a texture as Texture Parameter to a material created dynamically.

//1. I create the objects from the uasset when I receive the http response : 
LoadedMesh = Cast<UStaticMesh>(StaticLoadObject(UStaticMesh::StaticClass(), NULL, *MeshAssetName));
UMaterial *Material = Cast<UMaterial>(StaticLoadObject(UMaterial::StaticClass(), NULL, *AssetName ));
UTexture *MyTexture = Cast<UTexture>(StaticLoadObject(UTexture::StaticClass(), NULL, *AssetName));
// by the way I didn't find any clever way to find out what type an uasset is, so I did the following :
UTexture *MyTexture = Cast<UTexture>(StaticLoadObject(UTexture::StaticClass(), NULL, *AssetName));
if (!MyTexture) UMaterial *Material = Cast<UMaterial>(StaticLoadObject(UMaterial::StaticClass(), NULL, *AssetName ));

//2. then I generate a dynamic instance material from the main material : 
UMaterialInstanceDynamic* MaterialInstanceDynamic = UMaterialInstanceDynamic::Create(Material, MainObjectComponent);

//3. I apply one of my textures to my instanced material : 
MaterialInstanceDynamic->SetTextureParameterValue(ParameterFName, MyTexture);

//4. Finally I apply the material 
MainObjectComponent->SetMaterial(0, UMaterialInstanceDynamic );

Only the third part fails. And the surprising thing is that if I use as base material one from my scene like this :

UMaterial *Material = Cast<UMaterial>(StaticLoadObject(UMaterial::StaticClass(), NULL, TEXT("/Game/poduszka3_Mat.poduszka3_Mat")));
UMaterialInstanceDynamic* MaterialInstanceDynamic = UMaterialInstanceDynamic::Create(Material, MainObjectComponent);
MaterialInstanceDynamic->SetTextureParameterValue(ParameterFName, MyTexture);

Then it works.
And the other Materials all worked well as long as they have no texture parameter applied. It doesn’t matter either if the texture is dynamically loaded through a pak file or not.

Hi Schopi,
i v noticed that you made a system which can load pak files at runtime.
would you mind to share how you make it or where i can start?

Hi.
Yes, even if I didn’t manage to really solve this issue I do load pak files at runtime. By far the biggest help came from this thread . I didn’t use his plug in but I read it and adapted it to my own needs.

The most important class is FPak. There is not much documentation there, but it is still better to read it before starting.

Good luck with this

hi Schopi,

According to your advise, I have be able to load pak files at runtime. However, I am still wondering how could i dynamically load uasset files of material and mesh to create an instance of Static Mesh Actor with C++? Would you mind give me some tips?

hi Schopi,
I have the same problem that how to load .uasset files from .pak file, at runtime? would u mind give me some tips?
the following code doesn’t work as expected:

    IPlatformFile &PlatFormFile = FPlatformFileManager::Get().GetPlatformFile();
    FPakPlatformFile PakPlatForm;
    PakPlatForm.Initialize(&PlatFormFile, TEXT(""));
    FPakFile PakFile(PakFileName, false);
    UE_LOG(LogDynamicStaticMeshActor, Log, TEXT("Init - IsPakFileValid:%d"), PakFile.IsValid());
    FString MountPoint(TEXT("/Engine/Content/"));
    PakFile.SetMountPoint(*MountPoint);
    int32 PakOrder = 0;
    if (!PakPlatForm.Mount(PakFileName, PakOrder, *MountPoint)) {
        UE_LOG(LogDynamicStaticMeshActor, Fatal, TEXT("Mount error"));
    }

    TArray<FString> AssetFileNames;
    PakFile.FindFilesAtPath(AssetFileNames, *MountPoint);

    for (const FString &AssetName : AssetFileNames) {
        UE_LOG(LogDynamicStaticMeshActor, Log, TEXT("AssetName:%s"), *AssetName);
    }

    UStaticMeshComponent *StaticMeshComponent = NewObject<UStaticMeshComponent>(this, TEXT("staticMeshCom"));

    FStreamableManager StreamableManager;
    FStringAssetReference AssetRef(TEXT("/Engine/Content/BR_DongChenMingHan_6.BR_DongChenMingHan_6"));
    UMaterial *Material = Cast<UMaterial>(StreamableManager.SynchronousLoad(AssetRef));
    StaticMeshComponent->SetMaterial(0, Material);

Could u mind point out the problem? thank u very much!

The fact you say that this works:

UMaterial *Material = Cast<UMaterial>(StaticLoadObject(UMaterial::StaticClass(), NULL, TEXT("/Game/poduszka3_Mat.poduszka3_Mat")));

but this doesn’t:

UMaterial *Material = Cast(StaticLoadObject(UMaterial::StaticClass(), NULL, *AssetName ));

given that the rest of the lines are the same, makes me question whether there’s a bug with your AssetName.

the asset file name in the pak file is BR_DongChenMingHan_6.uasset

I can’t see how this line could work :

UStaticMeshComponent *StaticMeshComponent = NewObject<UStaticMeshComponent>(this, TEXT("staticMeshCom"));

Shouldn’t you be using *AssetName from your loop instead of staticMeshCom ?

I never used FStreamableManager. Can’t help you about this. Maybe you should ask a new question about this but explain more clearly what doesn’t work exactly. By example are the *AssetName logs from your loop fine ?

Thanks for your answer what you say makes sense.
But the AssetName is right because I get it from this function :

PakFile.FindFilesAtPath(PakContent, *PakFile.GetMountPoint(), true, false, true);
for (TSet<FString>::TConstIterator SetIt(PakContent); SetIt; ++SetIt)
{
	FString AssetName = *SetIt;
	UE_LOG(LogTemp, Log, TEXT(" --->>> Asset is mounted here  :: :: :: %s "), *AssetName);
}

And when I create it like you said, I don’t get any error message. And it is even possible to apply the material to a mesh, everything about the material works fine. It only fails if I apply a texture to one of the texture parameter of this dynamically loaded material.

I don’t think that you can dynamically load uasset files by themselves. They have to be part of a pak file. The uasset files from the pak file are what you get when you use the following function on you pakcontent :

PakFile.FindFilesAtPath(PakContent, *PakFile.GetMountPoint(), true, false, true);
 for (TSet<FString>::TConstIterator SetIt(PakContent); SetIt; ++SetIt)
 {
     FString AssetName = *SetIt;
     UE_LOG(LogTemp, Log, TEXT(" --->>> Asset is mounted here  :: :: :: %s "), *AssetName);
 }

Then *AssetName is the path that you should use to create your mesh instance like this :

UStaticMesh* LoadedMesh = Cast<UStaticMesh>(StaticLoadObject(UStaticMesh::StaticClass(), NULL, *MeshAssetName));

Sorry to be so slow, I hope that I correctly understood what is your problem.

I’ve ask another question, How to load assets from a pak file at runtime? - Rendering - Epic Developer Community Forums
thank u for your reply!