Server doesn't change variable on the client

Hello.
I’m making a multiplayer game.

Each player has its own CurrentWeapon, defined as follows:

	UPROPERTY(Transient, Replicated)
		AWeapon* CurrentWeapon;

and replicated as follows:

DOREPLIFETIME(AMyCharacter, CurrentWeapon);

I change the CurrentWeapon variable from the Server (because I want the server to change client’s variable).

void AWeapon::Fire()
{
        // HERE the call for the ServerRPC function
	if (Role < ROLE_Authority)
		ServerFire();

	else
	{
		// Weapon-specific shooting
		FireWeapon();

		// At the end of the shooting, decrease ammunitions
		DecreaseAmmo();

		// Check if out-of-ammo. If yes, switch weapon
		if (MyOwner->GetAmmo(WeaponConfig.PrimaryAmmo) == 0)
		{
			StopFire();
			MyOwner->ForceWeaponSwitch();

			return;
		}
              ... .... ...
	}

}

MyOwner is the PlayerCharacter owning the Weapon and ForceWeaponSwitch() is a PlayerCharacter function which simply changes the CurrentWeapon variable

The problem is that, after the ServerRPC call executes, the CurrentWeapon variable is still the same, it doesn’t change.

But why?

If I play in the Editor with 2 windows (one is the listen server player and the other one is a generic client) the variable changes in the ListenServer player, but doesn’t change in the other player (which is the client).

Yes, I edited the post above!

Could you also show your RPC function?

Are you sure the RPC is executed on the server (for the non-host player)?

Thanks, but it would be helpful to see all functions involved in the RPC, like ServerFire for example, if I remember correctly, there is ServerFire_Implementation and ServerFire_Validate as well.

Just a typo: ServerFire() is just the RPC function that calls the Fire() function again:

void AWeapon::ServerFire_Implementation()
{
	Fire();
}

bool AWeapon::ServerFire_Validate()
{
	return true;
}

Also yes, the function ForceWeaponSwitch is called on the Server. I made a check with DebugMessages

I am having a VERY similar problem in this Question: OnRepNotify doesn't work! - Programming & Scripting - Unreal Engine Forums

Could you check if the AWeapon actor to which you want to swich is replicated to the client?

The ForceWeaponSwitch() just calls the EquipPistol() function.

This is the EquipPistol()

	AWeapon* theWeapon = FindWeapon(EWeaponType::Pistol);

	if (theWeapon)
	{
		CurrentWeapon = theWeapon;
	}

AWeapon is the class of the Weapons as well as the class I call ForceWeaponSwitch() from. The player has an Inventory of Weapons, which is already replicated and has been used for other gameplay algorithms.

I can’t understand where the problem is.

Maybe just rewrite it on a different version of the engine?

Which UE4 version are you using?

It’s the 4.10 compiled from the GitHub source version.

I’m sure there’s something wrong… ■■■■ it :S

BUMP I need to solve this. Isn’t there any solution?

Could you try changing the variable type to a simple type like bool or int?
We could then see if this is related to the variable being a reference to UObject.

Ok in the MyCharacter::ForceWeaponSwitch() function (I remind you, called by the AWeapon class) I change a boolean that determines whether the character can move or not. Well, that works. That boolean changes value succeffully.

But still I can’t get the Weapon switch to happen.

AWeapon* , by the way, is a pointer to an object of AWeapon class (which derives from AActor)

89771-screenshot_2.jpg

Yes it is… or at least should be

The BeginPlay() function is always called by both the Server and the Client, so doing this

void AWeapon::BeginPlay()
{
	Super::BeginPlay();

	if (Role == ROLE_Authority)
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("SERVER")));
	}

	else
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, FString::Printf(TEXT("CLIENT")));
	}
}

Will display both the messages

So a bool change is replicated but the AWeapon* is not.
I would then guess that the instance of AWeapon is somehow not replicated properly on the client, but you said it is.
Therefore I have no other ideas.

Simplest way to check is to print to log from AWeapon::BeginPlay a message containing the actor’s net role.

So any idea?

If this is an important problem for you, you can try to isolate the issue:

Create an example with just the one class that needs to replicate a pointer to another actor. If the problem persists it may be an engine bug, if not, look at the difference between the minimal example and your project.

On the other hand, you can make a workaround:

  • set the weapon in a RPC or
  • replicate the EWeaponType instead