A C# client for Phoenix Channels.
Unity compatible. Powering Dama King.
- Full Phoenix Channels protocol support
- Modern async/await API with cancellation support
- Automatic reconnection and channel rejoin
- Presence tracking
- Customizable WebSocket and JSON implementations
- Unity and .NET Standard 2.0 compatible
dotnet add package PhoenixSharpInstall via openupm-cli:
openupm add io.level3.phoenixsharpOr add manually to Packages/manifest.json:
{
"scopedRegistries": [
{
"name": "package.openupm.com",
"url": "https://package.openupm.com",
"scopes": ["io.level3"]
}
],
"dependencies": {
"io.level3.phoenixsharp": "1.4.1"
}
}Alternatively, download the source and add it to your project, or use a Git submodule.
// Create and connect a socket
var socket = new Socket(
"wss://example.com/socket",
new Socket.Options(new JsonMessageSerializer())
);
socket.Connect();
// Join a channel
var channel = socket.Channel("room:lobby", new { userId = "123" });
channel.Join();
// Listen for events
channel.On("new_message", message => {
var payload = message.Payload.Unbox<ChatMessage>();
Console.WriteLine($"Received: {payload.Text}");
});
// Send messages
channel.Push("send_message", new { text = "Hello!" });await socket.ConnectAsync();
var result = await channel.JoinAsync();
if (result.IsSuccess)
{
var response = await channel.PushAsync<ChatMessage>(
"send_message",
new { text = "Hello!" }
);
if (response.IsSuccess)
Console.WriteLine($"Sent with id: {response.Response.Id}");
}
await channel.LeaveAsync();- Migration Guide - Upgrading from older versions
- Integration Tests - Complete usage examples
The library requires an IWebsocket implementation. Sample implementations are available in PhoenixTests/WebSocketImpl.
var factory = new MyWebSocketFactory();
var socket = new Socket(address, null, factory, options);Recommended implementations:
- NativeWebSocket (Unity) - Open source, supports WebGL/Android/iOS/UWP. Install via UPM, then import the sample adapter from the package.
- BestHTTP (Unity) - Commercial plugin, handles threading automatically. See sample adapter in the package.
- System.Net.WebSockets - Built-in .NET option, no additional dependencies
The default JsonMessageSerializer uses Newtonsoft.Json with the Phoenix V2 serialization format. To use a different serializer, implement IMessageSerializer and IJsonBox.
var options = new Socket.Options(new MyCustomSerializer());var presence = new Presence(channel);
presence.OnJoin += (key, current, newPresence) => {
Console.WriteLine($"{key} joined");
};
presence.OnLeave += (key, current, leftPresence) => {
Console.WriteLine($"{key} left");
};
// Wait for initial state (async)
await presence.WaitForInitialSyncAsync();For background on Unity's .NET support, see Microsoft's Unity scripting documentation.
By default, the library uses System.Threading.Tasks for timers and delays. For Unity, you can swap in a better executor via IDelayedExecutor. The recommended option is UniTask — import the sample from the package and use UniTaskDelayedExecutor for zero-allocation delays on Unity's PlayerLoop:
var options = new Socket.Options(serializer)
{
DelayedExecutor = new UniTaskDelayedExecutor()
};A coroutine-based executor is also available as a sample for projects that don't use UniTask.
The recommended WebSocket library for Unity is NativeWebSocket — an open-source, dependency-free WebSocket client that supports WebGL, Android, iOS, and UWP. Install it via UPM with the git URL, then import the NativeWebSocket sample adapter from the PhoenixSharp package in Unity's Package Manager.
Alternatively, BestHTTP is a commercial plugin that handles threading automatically. A sample adapter is also included in the package.
- UniTask - Zero-allocation async/await; use with the UniTask Delayed Executor sample for best performance
- NativeWebSocket - Open-source WebSocket client for Unity (WebGL/Android/iOS/UWP)
- BestHTTP - Commercial plugin, handles threading automatically
- com.unity.nuget.newtonsoft-json - Unity's official Newtonsoft.Json package
| Method | Description |
|---|---|
Connect() |
Connect to the server |
ConnectAsync() |
Connect asynchronously |
Disconnect() |
Disconnect from the server |
DisconnectAsync() |
Disconnect asynchronously |
Channel(topic, params) |
Create a channel |
| Method | Description |
|---|---|
Join() |
Join the channel |
JoinAsync() |
Join asynchronously, returns JoinResult |
Leave() |
Leave the channel |
LeaveAsync() |
Leave asynchronously |
Push(event, payload) |
Send a message |
PushAsync(event, payload) |
Send asynchronously, returns PushResult |
PushAsync<T>(event, payload) |
Send with typed response |
On(event, callback) |
Subscribe to events |
Off(event) |
Unsubscribe from events |
WaitForEventAsync(event) |
Wait for a single event |
| Method | Description |
|---|---|
OnJoin |
Event fired when a user joins |
OnLeave |
Event fired when a user leaves |
OnSync |
Event fired on state sync |
WaitForInitialSyncAsync() |
Wait for initial presence state |
WaitForUserAsync(key, timeout) |
Wait for a specific user |
# All tests
dotnet test
# Unit tests only
dotnet test --filter "Category!=Integration"
# Integration tests (requires server)
dotnet test --filter "Category=Integration"Integration tests run against phoenix-sharp.level3.io. Server source: phoenix-integration-tester
Issues and pull requests are welcome!
MIT
Maz (Mazyad Alabduljaleel)
Logo is a mix of Unity and Phoenix logos. Please don't sue me.
