In your Unity project, navigate to Assets -> Import Package -> Custom Package
Select the downloaded "NugetForUnity.3.0.4.unitypackage" and click Import All
Step 2 : Install Phoenix Client Package
Access NuGet Package Manager: Click NuGet (at the top of your Unity Editor) -> Manage NuGet Packages
Search for "io.sariska.sariskacsharp"
Click Install to add the Phoenix Client package to your project.
Step 3 : Import PhoenixSharp
usingPhoenix;usingPhoenixTests.WebSocketImpl;
Step 4 : Create Socket
Establish a WebSocket connection to the Sariska server to join channels, receive events, and send messages.
// Create a new WebSocket instance, specifying the server URL and authorization tokenvar socket =newSocket("wss://api.sariska.io/api/v1/messaging/websocket", {token:"your-token"});// Track the number of open connectionsvar onOpenCount =0;var onOpenCount =0;// Handles socket opening eventvoidOnOpenCallback() => onOpenCount++;socket.OnOpen+= OnOpenCallback;// Handles socket closing eventvoidOnClosedCallback() => onOpenCount--;socket.OnClose+= OnClosedCallback;// Initiate the connection to the serversocket.connect()
To disconnect the user from any previous WebSocket connections and tabs before opening a new one, set the disconnect_past_tabs parameter to true in the WebSocket connection.
Disconnect Socket
Close the WebSocket connection to the Sariska server. This will terminate all active channels and prevent further communication with the server.
// Close connection to the serversocket.disconnect();
Step 5 : Create Channel
Channels cannot be created directly; instead, they are created through the socket object by calling socket.channel(topic) with the topic of the channel. The topic is a string that identifies the channel, and it can be any string you like.
Channel Prefix
Each channel name starts with a prefix that determines the message serialization format and persistence behavior.
chat: Use this prefix for persisting messages to the database. This prefix requires a fixed schema and is ideal for chat applications.
var channel =socket.channel("chat:room123");
rtc: Use this prefix for scenarios where message persistence is not necessary. This prefix allows sending arbitrary JSON data, making it suitable for events in multiplayer games, IoT applications, and others.
var channel =socket.channel("rtc:room123");
sariska: Use this prefix for performance-critical applications that utilize Flatbuffers as the serialization format and do not require message persistence. This prefix provides zero-copy serialization/deserialization, significantly enhancing performance.
var channel =socket.channel("sariska:room123");
Handle Errors
When an error occurs on the channel, the ERROR callback is triggered. The callback receives the error information in payload, if available.
When the channel is closed, the CLOSE callback is invoked. This signifies that the communication on the channel has ended and no further data can be exchanged.
socket.OnClose+= OnClosedCallback;
Step 4 : Join and Leave Channel
To join a channel, call the join() method on the channel object. The join() method returns a promise that resolves when the client has successfully joined the channel. When sending data, you can utilize the .receive() hook to monitor the status of the outgoing push message.
// Join the channelReply? joinOkReply =null;channel.join() .receive("ok", r => joinOkReply = r) .receive("error", r => joinErrorReply = r) .receive("timeout", () =>Debug.log("Time out"))// Leave the channelchannel.leave();
Channel User Joined
channel.on("user_joined", (payload)=>{ var {user, room} = payload; });
Payload of user containing user details, including:
id: The user's ID
name: The user's name
avatar: The user's avatar URL
email: The user's email address
Payload of room containing room details, including:
id: The room's ID
session_id: The room's session ID
created_by: The ID of the user who created the room
status: The status of the room (e.g., "active", "inactive")
Payload of message containing message details, including:
content: The message content
id: The sender's user ID
name: The sender's name
content_type: The message content type (media, emoji, text)
is_delivered: Whether the message has been delivered to the recipient
created_by: The ID of the user who sent the message
created_by_name: The name of the user who sent the message
timestamp: The message timestamp
Send Message
Once you've established a connection to a channel, you can start sending messages to other connected clients. To send a message, use the push() method on the channel object.
// Send the new_vote event with the payloadchannel .Push("new_vote", payload) .Receive("ok", response => {Console.WriteLine($"Poll Vote Sent: {response}"); }) .Receive("error", response => {Console.WriteLine($"Error: {response}"); });
The first step is to install NuGetForUnity Package manager in your Unity project. The Package Manager is used to import Phoenix Client into your project.
First, you need to create the socket that will join channels, receive events, and send messages. A single connection is established to the server and channels are multiplexed over the connection.
var socket =newSocket("wss://api.sariska.io/api/v1/messaging/websocket", {token:"your-token"});// In the WebSocket connection, set params["disconnect_past_tabs"] to true if you want the user to disconnect from past WebSocket connections and tabs before establishing a new WebSocket connection.
var onOpenCount =0;var onOpenCount =0;voidOnOpenCallback() => onOpenCount++;socket.OnOpen+= OnOpenCallback;voidOnClosedCallback() => onOpenCount--;socket.OnClose+= OnClosedCallback;// Opens connection to the serversocket.connect()
Disconnect Socket
// Closes connection to the serversocket.disconnect();
Once your socket is created, you can join channel topics that listen for specific events and allow for sending data to do a topic. Whenever sending data, you can use the .receive() hook to get the status of the outbound push message. Channels cannot be created directly but instead are created through the socket object by calling socket.channel(topic) with the topic of the channel.
// Use prefix chat in your channel name if you want to persist messages to the database // here schema is fixed, only fixed fields are allowed to send, use this for chatting applicationsvar channel =socket.Channel("tester:phoenix-sharp", _channelParams);// Use prefix rtc in your channel name if you don't need any persistent // here you can any json object to other peers, this is useful for events in multiplayer games..etc var channel =socket.channel("rtc:room123");// Use prefix sariska in your channel name if want to use flatbuffers as serializer and ou don't need any persistent// here you are able to send any schema as per flatbuffers standard, use this for performance critical applications , gaming etc
var channel =socket.channel("sariska:room123");/// Called when errors occur on the channelvoidOnErrorCallback(string message) {onErrorData.Add(message); }socket.OnError+= OnErrorCallback;/// Called when the channel is closedsocket.OnClose+= OnClosedCallback;// channel user joined the eventchannel.on("user_joined", (payload)=>{ var {user, room} = payload; // { //user details // id: "1", // name: "nick", // avatar: "https://test.sariska.io/nick/profile.png", // email: "nick@gmail.com ", // } // { //room details // id: "1", // session_id: "room123", // created_by: "123456", // status: "active" // } //});// channel message received eventMessage? afterJoinMessage =null;channel.on("new_message", (message)=> { afterJoinMessage = message; // { //message details // content: "hello from rick", // id: '2', // sender user id // name: 'rick' // sender name // content_type: "media", // media, emoji, text etc // is_delivered: true, // timestamp: // } //});// Join the ChannelReply? joinOkReply =null;channel.join() .receive("ok", r => joinOkReply = r) .receive("error", r => joinErrorReply = r) .receive("timeout", () =>Debug.log("Time out"))// Leave the channelchannel.leave();
// Assuming you have a channel instance// Assuming you have a poll question and optionsvar pollQuestion ="What is your favorite color?";var pollOptions =newList<string> { "Red","Blue","Green" };// Build the payload with the poll question, content type, and optionsvar payload =new{ content = pollQuestion, content_type ="poll", options = pollOptions};// Send the new_vote event with the payloadchannel .Push("new_vote", payload) .Receive("ok", response => {Console.WriteLine($"Poll Vote Sent: {response}"); }) .Receive("error", response => {Console.WriteLine($"Error: {response}"); });
Next, use the presence.onSync callback to react to state changes from the server. For example, to render the list of users every time the list changes, you could write:
presence.list(by:) is used to return a list of presence information based on the local state of metadata. By default, all presence metadata is returned, but a listBy function can be supplied to allow the client to select which metadata to use for a given presence. For example, you may have a user online from different devices with a metadata status of "online", but they have set themselves to "away" on another device. In this case, the app may choose to use the "away" status for what appears on the UI. The example below defines a listBy function that prioritizes the first metadata which was registered for each user. This could be the first tab they opened or the first device they came online from:
Subscribe to the archived_message event to receive the last 1000 messages in reverse chronological order.
channel.On("archived_message", payload =>{if (payload.TryGetValue("messages",outvar messages) && messages isDictionary<string,object>) { // Process the received messagesConsole.WriteLine($"Received archived messages: {messages}"); }});
Subscribe to the archived_message_count event to get the total number of messages in the chat history.
channel.On("archived_message_count", payload =>{if (payload.TryGetValue("page",outvar page) && page isDictionary<string,object> && ((Dictionary<string,object>)page).TryGetValue("count",outvar count) && count isint) { // Process the received message countConsole.WriteLine($"Total message count: {count}"); }});
To retrieve a list of messages in the chat history, trigger the "archived_message" event to obtain the messages. Specify the "size" parameter to determine the number of messages you wish to fetch, and set the "offset" parameter as the starting index of the messages and group_by_day to group messages by date.
If you desire to receive the total count of messages at any given time, initiate the "archived_message_count" trigger and subscribe to the corresponding event by listening for "archived_message_count."
voidOnArchivedMessageCount(dynamic payload){if (payload["page"] isDictionary<string,dynamic> page) {if (page["count"] isint count) { // Process the received message countConsole.WriteLine($"Total message count: {count}"); } }}// Example usage:channel.On("archived_message_count", OnArchivedMessageCount);
Using the Messages API
Make a GET request to the API endpoint to fetch the chat history for a specific room.
Retrieve any specific message from a room. It takes the room ID and message ID as parameters and sends a GET request to the Sariska API to fetch the specified message.