How do I replicate a material from an object on the server to the corresponding object on the client?

Currently have a setup where I have some objects that the skins can be changed on (I swap out a texture in the material). Now I think I have wrongly assumed that when the objects replicated to the client, their materials and textures would also replicate with them, but it seems this is not the case.

Is there an approach I need to look at to make sure the objects on the client also have the same updated material as the server?

When an actor is marked as replicated, only the properties that are also marked as replicated will actually synchronize to all the clients connected to the server.

Normally properties are marked as replicated within the UPROPERTY keyword in the headers. If the property was added via blueprints, you can also mark that property as replicated there.

One other requirement is that the material object needs to have been loaded from a package to be net addressable.

If all these requirements are met, you should be able to replicate references to material properties.

One safe way to replicate something like a material change like you mentioned would be to maintain a separate array of materials that are replicated, and then set these as the skin when you detect they change through the OnRep mechanism.

When you say load from package, what exactly is meant by that?

Also, I set my objects material to also be replicated across

UPROPERTY(Replicated)
	UMaterialInstanceDynamic* m_BallMaterial;

but it still doesn’t seem to work correctly, guessing it has something to do with loading my texture with:

UTexture2D* tmpTexture = Cast(StaticLoadObject(UTexture2D::StaticClass(), NULL, *(PathName)));

Hi Dune,

Can you look at the logs on the server, and see if you find any lines that start with this:

UPackageMapClient::SupportsObject …

Thanks :slight_smile:

Sorry for the late replay, Easter weekend and all…however, seem to have a multitude of them:

LogNetPackageMap:Warning: UPackageMapClient::SupportsObject /Game/Maps/UEDPIE_1_OnlineMap.OnlineMap:PersistentLevel.Obj_BP_C_13.MaterialInstanceDynamic_36 NOT Supported.Not RF_WasLoaded. NetGUID: <0>

Is this something I’m doing at all, tried to find out what it was but couldn’t find much info on it?

Still not able to get the material to replicate across to the client. My material is all set to replicate on the actor that is being replicated, however the errors in the log files happen for each object/material it seems and I’m not exactly sure what those errors even relate to?

Hi Dune, it looks like that material was created at runtime, and in that case, won’t replicate as a reference properly. To replicate a material reference, it needs to be loaded from a package.

Is there a way to actually do this then? I can only use UMaterialInstanceDynamic in order to change the parameters of the material at runtime, but cannot seem to have this set in a blueprint, so instead I use a UMaterial but this doesn’t allow parameter changes?

What I need is:
Have the material set on each of my objects
Change the texture in code (SetTextureParam…)
This will then replicate across to the client, with the material showing the correct texture

You could use an RPC function (that takes the texture as parameter) that the server could use to communicate with clients of the texture change.

Hi, John. You mentioned that:

“One other requirement is that the material object needs to have been loaded from a package to be net addressable.”

Can you explain that a bit more? How do we know if the material is loaded from a package? Are materials created in UE4 automatically part of a package?

Hi folks,

I am very interested in an answer on this matter.

I am currently loading a image file (jpg, png…) at runtime and transform it into a UTexture2D. It works locally but i can’t find a way to share it across clients.

Cheers

Cedric

The only way I could replicate a material was by doing it in blueprints. I could not get a dynamic material created in C++ at runtime to work.

To anyone finding this a year later, like me ; )

I had the same problem, to replicate a material to my clients, only in my case I used a UMaterialInterface* myMaterial on the server. Simply replicating this to my clients didn’t do anything.

The problem is the same with an Actor’s rotation, or location, or anything. These values are replicated, but they aren’t actively set, which means the “SetMaterial” or “SetRotation” or “SetLocation” has to be called when the material changes.

I imagine this is what RepNotify is for exactly, because if you create this event on replication:

UPROPERTY(ReplicatedUsing = OnRep_SetMaterial)
UMaterialInterface* myMaterial;
UFUNCTION()
virtual void OnRep_SetMaterial();

… and then in the cpp you add “myMaterial” in the DOREPLIFETIME Macro along with all your other variables, and implement:

void AAnyActor::OnRep_SetMaterial(){
// this now actively sets the material, and it shows up on the clients
this->Mesh->SetMaterial(0,myMaterial);
}

At least this works perfect for me : )

1 Like

Thank you for sharing.
In my case I’m using a Character blueprint.
I created a new variable of type Material reference, and set replication type to RepNotify. Unreal created a function for me called “OnRep_MaterialToLoadInClothes” automatically and inside this function I put the Set Material node call. This way both the client and server loads the material.

Regards

1 Like

Rockseller, you are my hero today! :)))

Hello,

You can use this plugin for multiplayer texture replication.

Unreal Engine

Replicated Texture - UE Marketplace

Built-in Multiplayer Replicated Texture without external network system ( HTTP, website … )

Texture replication is available for Windows, Android, iOS, Oculus, Linux.

Bandwidth usage is optimized, the texture data sent via network are compressed using external image compression library and then uncompressed when received.

1 Like