Skip to main content

Remote Calls

Replication handles syncing data automatically, but sometimes you need to explicitly tell the server or a client to do something. That's what Remote Procedure Calls (RPCs) are for -- they let you call a function on one machine and have it execute on another.

Three Types of RPCs

HELIX supports three RPC types, each for a different direction:

Server Functions

Called from a client, executed on the server. Use these when a player wants to do something that requires server authority -- like dealing damage, purchasing an item, or requesting a spawn.

// Header: mark as Server RPC
UFUNCTION(Server, Reliable)
void Server_RequestAttack(AActor* Target);

// Implementation runs on the server
void AMyCharacter::Server_RequestAttack_Implementation(AActor* Target)
{
// Validate and apply damage on the server
if (Target && IsValid(Target))
{
UGameplayStatics::ApplyDamage(Target, 25.0f, GetController(), this, nullptr);
}
}

Client Functions

Called from the server, executed on a specific client. Perfect for sending personalized information -- like showing a notification, playing a sound only that player should hear, or updating their UI.

// Header: mark as Client RPC
UFUNCTION(Client, Reliable)
void Client_ShowNotification(const FString& Message);

// Implementation runs on the owning client
void AMyCharacter::Client_ShowNotification_Implementation(const FString& Message)
{
// Display a UI notification for this player
ShowOnScreenMessage(Message);
}

Multicast Functions

Called from the server, executed on all clients (and optionally the server too). Great for global events like explosions, weather changes, or announcements.

// Header: mark as NetMulticast RPC
UFUNCTION(NetMulticast, Reliable)
void Multicast_PlayExplosion(FVector Location);

void AMyActor::Multicast_PlayExplosion_Implementation(FVector Location)
{
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ExplosionFX, Location);
}

Reliable vs. Unreliable

RPCs can be Reliable (guaranteed delivery, ordered) or Unreliable (faster, but might get dropped). Use Reliable for important gameplay events like damage or purchases. Use Unreliable for frequent, non-critical updates like cosmetic effects.

Best Practices

  • Always validate on the server. Never trust data coming from a client RPC -- check that the action is legal before applying it.
  • Keep payloads small. Send IDs or indices instead of full objects when possible.
  • Don't spam RPCs. If you're calling an RPC every frame, you probably want replication instead.
  • Use Multicast sparingly. Broadcasting to every client is expensive -- consider whether relevancy-based replication would work better.