client change material server can not seen on unreal engine multiplayer c++

When Client Hover Mouse:
This time client side material change and server side can’t change material in C++

When Server Hover Mouse:
This time client & server both side change material in c++

How to fix this issue… in c++ ue5

`
#include “CoreMinimal.h”
#include “GameFramework/Actor.h”
#include “CppWeapon.generated.h”

// Forward Declares
class USphereComponent;
class UWidgetComponent;

UCLASS()
class ONLINECHESSGAME_API ACppWeapon : public AActor
{
GENERATED_BODY()

public:
ACppWeapon();
virtual void Tick(float DeltaTime) override;
virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override;

protected:
virtual void BeginPlay() override;
virtual void NotifyActorBeginCursorOver();
virtual void NotifyActorEndCursorOver();
UFUNCTION()
void OnRep_Material();

private:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = “ChessBoard”, meta = (AllowPrivateAccess = “true”))
UStaticMeshComponent* _markerBoardMesh;

private:
UPROPERTY(VisibleAnywhere, Category = “Weapon Properties”)
USkeletalMeshComponent* _weaponComponent;
UPROPERTY(VisibleAnywhere, Category = “Weapon Properties”)
USphereComponent* _areaSphere;
UPROPERTY(Replicated)
bool _markerVisible;
UPROPERTY(ReplicatedUsing = OnRep_Material)
UMaterialInstance* _material0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = “ChessBoard”, meta = (AllowPrivateAccess = “true”))
UMaterialInstance* _material1;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = “ChessBoard”, meta = (AllowPrivateAccess = “true”))
UMaterialInstance* _material2;

private:
UPROPERTY(Replicated)
FVector _location;
void AAAA_Material();
void BBBB_Material();
private:
void ChnageLocation(float DeltaTime);
UFUNCTION(Server, Reliable)
void ServerChnageMaterial(UMaterialInstance* material, bool isVisible);

public:
void SetWeaponLocation(bool isvisible, UMaterialInstance* material);
};

`

`
#include “CppWeapon.h”
#include “Components/SphereComponent.h”
#include “Components/WidgetComponent.h”
#include “Net/UnrealNetwork.h”
ACppWeapon::ACppWeapon()
{
PrimaryActorTick.bCanEverTick = true;
AActor::bReplicates = true;
this->_weaponComponent = CreateDefaultSubobject(TEXT(“Weapon Mesh”));
this->_weaponComponent->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block);
this->_weaponComponent->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore);
this->_weaponComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
AActor::SetRootComponent(this->_weaponComponent);
this->_areaSphere = CreateDefaultSubobject(TEXT(“Area Sphere”));
this->_areaSphere->SetupAttachment(AActor::RootComponent);
this->_areaSphere->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
this->_areaSphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);
this->_markerBoardMesh = CreateDefaultSubobject(TEXT(“MarkerBoard”));
this->_markerBoardMesh->SetupAttachment(AActor::RootComponent);
}
void ACppWeapon::BeginPlay()
{
Super::BeginPlay();
this->_location = this->GetActorLocation();
AActor::bReplicates = true;
AActor::SetReplicateMovement(true);
this->_areaSphere->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
this->_areaSphere->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Overlap);
}
void ACppWeapon::NotifyActorBeginCursorOver()
{
Super::NotifyActorBeginCursorOver();
this->AAAA_Material();
}
void ACppWeapon::NotifyActorEndCursorOver()
{
Super::NotifyActorEndCursorOver();
this->BBBB_Material();
}
void ACppWeapon::OnRep_Material()
{
this->_markerBoardMesh->SetMaterial(0, this->_material0);
this->_markerBoardMesh->SetVisibility(this->_markerVisible);
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString(“2020202020”));
}
void ACppWeapon::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ACppWeapon::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ACppWeapon, _location);
DOREPLIFETIME(ACppWeapon, _markerVisible);
DOREPLIFETIME(ACppWeapon, _material0);
}
void ACppWeapon::AAAA_Material()
{
this->SetWeaponLocation(true, this->_material1);
}
void ACppWeapon::BBBB_Material()
{
this->SetWeaponLocation(true, this->_material2);
}
void ACppWeapon::ChnageLocation(float DeltaTime)
{
FVector newLocation = FMath::VInterpTo(this->GetActorLocation(), this->_location, DeltaTime, 10.0f);
AActor::SetActorLocation(newLocation);
this->SetActorLocation(newLocation);
}
void ACppWeapon::SetWeaponLocation(bool isvisible, UMaterialInstance* material)
{
this->_material0 = material;
this->_markerVisible = isvisible;
this->_markerBoardMesh->SetMaterial(0, _material0);
this->_markerBoardMesh->SetVisibility(this->_markerVisible);
}
void ACppWeapon::ServerChnageMaterial_Implementation(UMaterialInstance* material, bool isVisible)
{
if (!HasAuthority())
{
ServerChnageMaterial(material, isVisible);
}
GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Red, FString(“Server Call”));
this->_markerBoardMesh->SetMaterial(0, _material0);
this->_markerBoardMesh->SetVisibility(this->_markerVisible);
OnRep_Material();
}

`

Hey there @BijayAdhikari96!

Thank you for providing background information and code snippets related to your question! Providing this information allows understanding the question and answering it in the first place. Next time though, please format your code snippet’s indentation as it will make it much more readable.

As far as the problem you are having, you seem to not have understood some core concepts of networking. Please have a look at Network in Unreal | An Unreal Engine Blog by Cedric Neukirchen (cedric-neukirchen.net), especially the RPC section.

Basically, Unreal uses the Client-Server model of networking and the only authority is the server. So whatever the server says, applies and NOT the other way around. This here is the crux of your problem.

In your case, on the client instance, when the client hovers his mouse over the object, the NotifyActorBeginCursorOver() function gets called. In here, you are changing the Material by calling AAAA_Material() which in turn calls SetWeaponLocation(bool isvisible, UMaterialInstance* material). But as NotifyActorBeginCursorOver() is being run on the client, the material only changes on the client and there is no client to server replication (remember, property replication is only from the server to the client)

What you want to do here instead is, call your Server RPC if NotifyActorBeginCursorOver() is being run on the client. Then react to any property changes in the OnRep functions, to apply the newly replicated material and visibility on the client.

//ACppWeapon.h
protected:

UPROPERTY(ReplicatedUsing = OnRep_bIsVisible)
bool bIsVisible;

UFUNCTION()
OnRep_bIsVisible(); 

//ACppWeapon.cpp
void ACppWeapon::ServerChangeMaterial_Implementation(UMaterialInstance* material, bool isVisible)
{
    //If we are not running on the server, return
    if (!HasAuthority())
    {
        return;
    }
    _material0 = material;
    bIsVisible = isVisible;
    
    //the function call below will apply the material changes on the server
    //look inside SetWeaponLocation to understand better
    SetWeaponLocation(isVisible, material);
}

//Because you have set the _material0 variable as a UPROPERTY(ReplicatedUsing = OnRep_Material), this function will run on the client once the server's version of _material0 has replicated down to the client
void ACppWeapon::OnRep_Material()
{
    this->_markerBoardMesh->SetMaterial(0, this->_material0);
    GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString(“2020202020”));
}

//Because you have set the bIsVisible variable as a UPROPERTY(ReplicatedUsing = OnRep_bIsVisible), this function will run on the client once the server's version of bIsVisible has replicated down to the client
void ACppWeapon::OnRep_bIsVisible()
{
    _markerBoardMesh->SetVisibility(bIsVisible);
    GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString(“2020202020”));
}

void ACppWeapon::NotifyActorBeginCursorOver()
{
    Super::NotifyActorBeginCursorOver();
    AAAA_Material();
}

void ACppWeapon::AAAA_Material()
{
    SetWeaponLocation(true, this->_material1);
}

void ACppWeapon::SetWeaponLocation(bool isVisible, UMaterialInstance* Material)
{ 
    //If we are on the client, we want to call the RPC to make the server change its material instance
    //This change will then trickle down upon replication to the client, and it will call its relevant OnRep functions if we have declared the UPROPERTYs to use OnRep functions
    if(!HasAuthority)
    {
        ServerChangeMaterial(Material, isVisibile);
        return;
    }

    //As we are already on the server, we can apply all the changes
    //The client will have to react accordingly
    _material0 = Material;
    _markerVisible = isVisible;
    _markerBoardMesh->SetMaterial(0, _material0);
    _markerBoardMesh->SetVisibility(_markerVisible);
}

Note: The approach above will add a slight network delay, as the material and visibility change first goes to the server, then comes back to the client in form of replication and then is applied. To avoid this, you could just call the Server RPC as above and then also apply the changes locally to the client. This would also remove the need for RPCs. I wrote the code snippet the way I wrote it to better explain what is happening in terms of networking. (Give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime)

Hope this helps. The code might have syntactical or other errors but it should be understandable what it is doing.