NetworkMessenger
Central messaging hub for the Messenger subsystem. Wraps Unity Netcode's CustomMessagingManager to provide a typed, callback-driven API for sending and receiving network messages. Manages a registry of NetworkMessageHandler instances keyed by handler ID, handles connection lifecycle, and implements the server relay pattern for client-to-client communication.
Definition
Namespace: Paragon.Core.Network Assembly: Paragon.dll
public class NetworkMessengerRemarks
NetworkMessenger is owned by the NetworkManager singleton and is accessible via NetworkManager.Messenger.
The messenger uses Netcode's unnamed message API (SendUnnamedMessage / OnUnnamedMessage). All routing is handled in the payload itself — the handler ID and target client IDs are written into the buffer alongside the serialized message.
Routing Strategy
Server sends: Messages go directly to the specified target clients via
SendUnnamedMessage(targetClientIds, writer).Client sends: Messages always go to the server via
SendUnnamedMessage(ServerId, writer). The server's NetworkMessageHandler then relays to the actual target clients.
Wire Format
The FastBufferWriter payload is structured as:
[senderClientId: ulong]
[handlerId: string]
[targetClientIds: ulong[]]
[messageHeader: string] ← typeof(TMessage).AssemblyQualifiedName
[NetworkMessage<TMessage>] ← INetworkSerializable payloadQuick Lookup
Access the messenger
NetworkManager.Messenger
Subscribe to messages
messenger.SubscribeToMessage<T>("handlerId", callback)
Send to specific clients
messenger.SendMessage(senderId, "handlerId", payload, clientId1, clientId2)
Broadcast to all clients
messenger.SendMessage(senderId, "handlerId", payload) (no target IDs)
Constructor
NetworkMessenger()
Creates the messenger and subscribes to NetworkManager.API.OnClientStarted and OnClientStopped for connection lifecycle management.
The messenger does not become functional until OnConnect() fires, which initializes the reference to CustomMessagingManager and subscribes to OnUnnamedMessage.
Methods
SubscribeToMessage<TMessage>
Registers a callback for a specific message type under a handler ID. If no handler exists for the given ID, one is created. Multiple callbacks can be registered for the same handler and message type.
handlerId
string
The handler group to subscribe to
callback
Action<TMessage>
The callback invoked with the deserialized payload
Type safety at the handler level: All subscriptions and sends for a given handlerId must use the same TMessage type. Subscribing with type A and sending with type B on the same handler ID will cause an InvalidCastException when the handler is retrieved.
SendMessage<TMessage>
Serializes and sends a typed message to the specified target clients. If no target IDs are provided, broadcasts to all connected clients (excluding the sender and the server itself when sending from the server).
senderClientId
ulong
The client ID of the sender
handlerId
string
The handler group to target
message
TMessage
The payload to send
targetClientIds
params ulong[]
Target client IDs. Empty = broadcast.
Routing behavior:
Server
Yes
Sends directly to specified clients
Server
No
Sends to all connected clients (excluding sender and server)
Client
Yes
Sends to server; server relays to targets
Client
No
Sends to server only
When no targets are specified and the sender is a client, the message is sent to the server. To broadcast from a client to all other clients, the server-side handler relay takes care of forwarding.
Connection Lifecycle
Common Pitfalls
Self-send is rejected If the sender's client ID matches the receiver's client ID, the message is logged as a warning and dropped. Messages cannot be sent to yourself.
Missing handler throws exception If a message arrives with a handlerId that has no registered handler, OnMessageReceived() throws an Exception. Ensure all handlers are subscribed before any messages can arrive on the network.
Fixed buffer size SendMessage() allocates a FastBufferWriter with 1024 bytes (Allocator.Temp). Messages with large payloads (e.g., long strings or complex INetworkSerializable types) may exceed this buffer. Be mindful of payload size.
Handler type mismatch A handler created via SubscribeToMessage<A>("id", ...) stores a NetworkMessageHandler<A>. If you later call SubscribeToMessage<B>("id", ...) with the same handler ID but a different type, the internal cast (NetworkMessageHandler<B>)handler will fail with InvalidCastException.
Examples
Basic Chat System
Targeted Damage Message
Custom Serializable Payload
See Also
NetworkMessageHandler — per-handler callback management and deserialization
NetworkMessage<TPayload> — serializable message wrapper
NetworkManager — singleton that owns the
MessengerinstanceMessenger Subsystem — subsystem overview
Last updated