Server RPC Cannot be called on the Client

So I have just started working on a new project in Unreal which is intended to be a simple networked multiplayer game. What I have done so far is make a Weapon class that handles the spawning of projectiles, and give the player character an instance of a weapon on BeginPlay.

Here is how I spawn the weapon on the player inside of BeginPlay:


    if (StartWeapon != NULL)
    {
        UWorld* const World = GetWorld();
        if (World)
        {
            // Set the spawn paramaters
            FActorSpawnParameters SpawnParams;
            SpawnParams.Owner = this;
            SpawnParams.Instigator = Instigator;

            // Spawn the pickup
            CurrentWeapon =
                World->SpawnActor<AWeapon>(StartWeapon, SpawnParams);
        }
    }

    // Attatch the weapon to the grip point on the player
    if (CurrentWeapon != nullptr && Mesh1P != nullptr)
    {
        if (CurrentWeapon->GetMesh() != nullptr)
        {
            const FName GripSocketName = FName(TEXT("GripPoint"));

            CurrentWeapon->GetMesh()->AttachToComponent(
                Mesh1P,
                FAttachmentTransformRules::SnapToTargetNotIncludingScale,
                GripSocketName);
            UE_LOG(LogTemp, Warning, TEXT("Setup the Current Weapon!!"));

        }
    }

The weapon class is simple, but the problem that I am having is that the Server RPC I have for spawning projectiles is not being called from clients, only servers.

Here is how I am calling this RPC:

The Player Character has an OnFire method, that is bound to an input action.
This then calls the Fire method on the current weapon that the player has.


    // Bind fire event
    PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AMultiplayerFPSCharacter::OnFire);

     ...

     void AMultiplayerFPSCharacter::OnFire()
     {
          // Call our weapon's fire method
          if (CurrentWeapon)
          {
              CurrentWeapon->Fire(GetControlRotation());
          }
     }

Now, the weapon’s Fire method simply calls the Server RPC to actually handle spawning the projectiles.


     void AWeapon::Fire(const FRotator SpawnRotation)
     {
          UE_LOG(LogTemp, Warning, TEXT("LOCAL Fire"));


          Server_Fire(SpawnRotation);
     }

     void AWeapon::Server_Fire_Implementation(const FRotator SpawnRotation)
     {
        UE_LOG(LogTemp, Warning, TEXT("SERVER RPC: Called RPC"));


        // try and fire a projectile
        if (ProjectileClass != NULL)
        {
            // Spawn Projectile
            ....
        }
     }

I also have the validation method for the Server RPC, which simply returns true for this so I can make sure it actually works.

This implementation is all fine and good on the server or Listen-Server, but when I call it from the client I only get the local Fire method on the Weapon. The client never even calls the server RPC.

One work around that I think I have found is to make the Player Character’s OnFire method a Server RPC as well, but this feels like it is not the best way to go about doing this.

Could anyone explain why this is happening?

I think the ShooterGame has a pattern for this. You should check for HasAuth in the Fire function and then call a spawn function from there, else call the ServerFire wich just calls the Fire function back. As you now are auth on the server the spawn function will be called.

Edit: To quick to soon, that will probably not fix your problem. Check that the owner really is set to the Character in the weapon.

Better use this way:


void AWeapon::Fire(const FRotator SpawnRotation)
{
    UE_LOG(LogTemp, Warning, TEXT("LOCAL Fire"));

    if (Role < ROLE_Authority)
    {
        Server_Fire(SpawnRotation);
    }
    // try and fire a projectile 
    if (ProjectileClass != NULL)
    {
        // Spawn Projectile .... }
    }
}



void AWeapon::Server_Fire_Implementation(const FRotator SpawnRotation)
{
    UE_LOG(LogTemp, Warning, TEXT("SERVER RPC: Called RPC"));

    Fire(SpawnRotation);
}

Also set owner for weapon class. By default weapon is not owned by player character(or other character). And cannot accept RCP calls as it exist as world owned actor, not client.

Here is the part of code from Shooter Game to setup owner:


void AShooterWeapon::SetOwningPawn(AShooterCharacter* NewOwner)
{
    if (MyPawn != NewOwner)
    {
        Instigator = NewOwner;
        MyPawn = NewOwner;
        // net owner for RPC calls
        SetOwner(NewOwner);
    }    
}

I think that my problem is coming from how I spawn the weapon itself. I have since looked at the ShooterGame example project, and honestly the way that project does this seems very convoluted and complex. However, I do like the the way that they implement the Server functions, just calling the local version of the function back and handling it all in that method.

What I did what change how my character creates and equips the weapon and it seems to have fixed the issue.

I’m not all the way there yet, but I am on the way. I will post my full solution when I get it to fully work how I would like.

Thank you very much for the responses you guys!