Download

How to call Server function from client on a level placed Actor?

I have an Actor placed on a level, and I would like to be able to call a Server function from a client.

I know that Server functions can be called only on client-owning actors, that’s why I’m doing this in the BeginPlay() of the actor:



 void AMyActor::BeginPlay()
{    
    Super::BeginPlay();
    SetOwner(UGameplayStatics::GetPlayerController(GetWorld(), 0));
}  


And then I try to call a Server function when something happens in the Tick() method. The server function only prints something in the log, and looks like this:




// In the .h:
UFUNCTION(Server, Reliable, WithValidation)
void ServerDoSomething();

// In the .cpp
void AMyActor::ServerDoSomething_Implementation()
{
    UE_LOG(LogTemp, Warning, TEXT("I made it"));
}

bool AMyActor::ServerDoSomething_Validate()
{        
     return true;
}  
 

By setting the owner in the BeginPlay() the error about “owning connections” goes away, but the actual method is NEVER called in the server. It just does nothing. So, how can I call a server function from an Actor placed in a level?

Unless the server also has your player set as owner, it will ignore the call.

Do you need to be able to use this from multiple players? Then I don’t think there’s a way other than adding a proxy function to the player controller (with a ptr to the actor) and have that call the actual function.

Yes, this object is “shared” among the players.It’s not the “cleanest” solution, but if there is no other way that should work :slight_smile:

Thanks!

If you do go that way, make sure the actor is actually valid on the server side, otherwise malicious client could crash the server by sending a nullptr

Thanks for the tip!

Could you please elaborate on how to do this? I’m working on a board for my RPG System and I need all players to be able to move the pieces.

You will need a start and end function and your server functions you made.
Example code, but it should work



/*
MoveYourPiece() CLIENT MOVES YOUR PIECE Start functon from button or what ever trigers it
*/
void AYourClass::MoveYourPiece()
{
     ENetMode NetMode = GetNetMode();

     SetThePiece();

     if (NetMode == NM_Client)
     {
        ServerDoSomething();
      }
}

// In the .cpp
void AMyActor::ServerDoSomething_Implementation()
{
    UE_LOG(LogTemp, Warning, TEXT("I made it"));
    SetThePiece();
}

bool AMyActor::ServerDoSomething_Validate()
{
    return true;
}

/*
SetThePiece(); end function to actually move the piece
*/
void AYourClass::SetThePiece()
{
     bMovePiece = !bMovePiece;//you will want to replicate this to everyone but yourself, if you need this

     //rest of your code to actually move your piece
}


Thank you!!

I checked your reply a few days ago and you pointed me into the right direction!! Just replying to thank you for taking the time to help!!
It worked!!