~/readme

PurrPipes

Peer-to-peer and relay network pipes for PurrNet. Offload bandwidth-heavy data like voice chat, video, or file transfers off the game server and send it directly between players.

Why?

Your game server doesn't need to relay every voice packet or video frame. PurrPipes lets players exchange data through direct P2P connections or lightweight relay servers, keeping your main server free for gameplay logic.

Features

  • P2P pipes for direct player-to-player connections (lowest latency)
  • Relay pipes when NAT traversal isn't an option (no port forwarding needed)
  • Automatic connection pooling so multiple relay pipes to the same server share one connection
  • Server-brokered authentication where peer identity is verified through one-time tokens, not self-reported
  • Transport agnostic use about any transport you want
  • Built-in reconnection for relay pipes on disconnect
  • Multiple pipes per player for separate data channels (voice, video, etc.)

Quick Start

Relay Pipe (recommended for most cases)

  1. Add PurrRelayPipe to your player prefab
  2. Set the master server URL in the inspector (a dev server is provided by default)
  3. Pick a region from the dropdown or hit "Find Best Region"
  4. That's it. Connection pooling and auth happen automatically.

P2P Pipe (UDPPipe is mostly an example here)

  1. Add UDPPipe to your player prefab
  2. The owner automatically starts listening on a UDP port
  3. Observers connect directly to the owner

Sending and Receiving Data

// Broadcast data from your pipe (on the owner's player)
var myPipe = GetComponent<PurrRelayPipe>();
myPipe.Broadcast(audioData, Channel.Unreliable);

// Listen for data on another player's pipe
var otherPipe = otherPlayer.GetComponent<PurrRelayPipe>();
otherPipe.onDataReceived += (senderPipe, data) =>
{
    PlayAudio(senderPipe.owner.Value, data);
};

// Or use the non-generic base class when you don't know the concrete type
NetworkPipe pipe = otherPlayer.GetComponent<NetworkPipe>();
pipe.onDataReceivedUntyped += (senderId, data) =>
{
    HandleData(senderId, data);
};

How It Works

P2P Topology

The pipe owner runs a mini server. Observers connect as clients directly to the owner's address. Low latency, but requires network conditions that allow direct connections.

Relay Topology

All players connect to a shared relay server as equal peers. The relay forwards packets between them. Slightly higher latency (extra network hop), but works behind any NAT. If the relay goes down the pipe reconnects automatically.

Authentication

Neither topology trusts players to identify themselves. Instead:

  1. A player requests pipe access via a ServerRpc
  2. The game server generates a one-time token
  3. The server sends the token to both the owner and the requesting player through separate TargetRpcs
  4. The requesting player presents the token over the pipe transport
  5. The owner validates it and maps the connection to a verified PlayerID

Tokens are single-use and cleaned up after auth. Players can't spoof their identity because the token comes from the server, not from the player.

Data Trust Model

PurrPipes verifies who is sending data but makes no guarantees about what they send. The game server never sees pipe traffic. This is by design: you get bandwidth savings in exchange for trusting that authenticated peers aren't sending garbage. Validate on the receiving end if you need to.

~/versions

Log in and subscribe to the Studio plan to access this package.

Log In