Cannot execute RPC on Server

I’m trying to execute a function on the server to fill in some blackboard values and cannot get it to execute. The general setup is that the player has a pawn which issues orders to other AI controlled characters. The relevant code is:

.h

UFUNCTION(Server, Reliable, WithValidation)
virtual void Server_MoveToLocation(FVector destination);
virtual void MoveToLocation(FVector destination);

.cpp


void ABaseCharacter::MoveToLocation(FVector destination)
{
	if (Role < ENetRole::ROLE_Authority)
	{
		Server_MoveToLocation(destination);
	}
	else
	{
		AAIController* ai = Cast<AAIController>(GetController());
		ai->GetBlackboardComponent()->SetValueAsVector("TargetLocation", destination);
	}
}

void ABaseCharacter::Server_MoveToLocation_Implementation(FVector destination)
{
	MoveToLocation(destination);
}

bool ABaseCharacter::Server_MoveToLocation_Validate(FVector destination)
{
	return true;
}

Some things which make this different from other questions I’ve seen:

  • I have set the owner on the Actor, on the server, and when I unset it I get a log saying that the RPC is rejected: “No owning connection for actor TopDownCharacter_C_0. Function Server_MoveToLocation will not be processed.”
  • When the owner of the Actor is set, I don’t get any error logs but the function does not get executed.
  • The AI Character is spawned on the server, in the player controllers OnPossess() callback
  • On the client, the actor is owned locally checked by using IsOwnedBy(UGameplayStatics::GetPlayerController(this, 0));
  • Using NetworkProfiler.exe I can see that the RPC is actually going over the network.
  • The code works fine in single player but launching with a dedicated server or with a listen server with a client it does not execute.
  • I have tried to verify whether the function is executing using logs, breakpoints and forcing null pointer exceptions, so it doesn’t even seem to be executed

Any help would be much appreciated. Are there any network debugging tools that I haven’t mentioned which might be useful?

Thanks!

client can only send ServerRPC to his owned actors. this is mostly because of security so that other clients can’t change your stuff buy calling those Server RPCs.
if your AI character has no owner or can be directed by anyone send the RPC from PlayerController.

class AMyPlayerController : public APlayerController
{
	UFUNCTION(Server, WithValidation, Reliable)
	void ServerMoveAIToLocation(ACharacter* aiChar, FVector destination);
	
	void ServerMoveAIToLocation_Implementation(ACharacter* aiChar, FVector destination)
	{
		AAIController* ai = Cast<AAIController>(aiChar->GetController());
		ai->GetBlackboardComponent()->SetValueAsVector("TargetLocation", destination);
	}
}

Hi, thanks for the response. As I said in the question the actor is owned by the PlayerController, and if I don’t manually make it owned by the PlayerController it gives me an error message saying there is no owning connection.

1 Like

You probably figured this out long ago, but to anyone else having this problem and landing here via a google search:
The issue is that APawn override’s GetNetConnection like so:

class UNetConnection* APawn::GetNetConnection() const
{
	// if have a controller, it has the net connection
	if ( Controller )
	{
		return Controller->GetNetConnection();
	}
	return Super::GetNetConnection();
}

So, if you have a pawn controlled by an AIController, it’ll use the NetConnection of the AIController even though you’ve set the network owner with SetOwner().

The fix is to override GetNetConnection yourself for pawns controlled by an AIController:

UNetConnection* ABaseBotCharacter::GetNetConnection() const
{
	if ( GetOwner() )
	{
		return GetOwner()->GetNetConnection();
	}
	return Super::GetNetConnection();
}
2 Likes

How can i do this using Blueprints plzzzzz … If no, is there a workaround? I’m getting this exactly problem.

You can always just use the player controller or its pawn as a bridge from the client to server to get an RPC to run.

Instead of:
AI Pawn (Client) → RPC → AI Pawn (Server)

It would be more like:
AI Pawn (Client) → Local Player Controller (Client) → RPC → Player Controller (Server) → AI Pawn (Server)

2 Likes

Thanks!! Worked perfectly. I don’t know if this is a good practice or not. I am passing all RPC calls (Client → Server) through the PlayerController and the PlayerController makes the call to the Actor that holds the necessary logic. It’s practically just a hop.