Chat System¶
GameFuse provides a flexible chat system that allows players to communicate directly with each other and in groups. The GameFuseUser.Chats
partial class contains methods to create and manage chats and messages within your game.
Chat System Methods¶
All chat methods are accessible through the GameFuseUser
instance after a successful login.
GetChatsAsync¶
Retrieves a paginated list of both direct and group chats for the current user.
Parameters:
- int page = 1
(optional): Page number for pagination
Returns:
- Task<GetChatsResponse>
: Response containing direct and group chats
Example:
try
{
// Get the current authenticated user
GameFuseUser currentUser = GameFuseUser.CurrentUser;
// Get the user's chats (first page)
GetChatsResponse chatsResponse = await currentUser.GetChatsAsync();
// Access direct chats
Chat[] directChats = chatsResponse.DirectChats;
// Access group chats
Chat[] groupChats = chatsResponse.GroupChats;
// Display the chats
Debug.Log($"Found {directChats.Length} direct chats and {groupChats.Length} group chats");
foreach (Chat chat in directChats)
{
string participantNames = string.Join(", ", chat.Participants.Select(p => p.Username));
Debug.Log($"Direct Chat ID: {chat.Id}, Participants: {participantNames}");
}
}
catch (ApiException ex)
{
Debug.LogError($"Failed to get chats: {ex.Message}");
}
CreateDirectChatAsync¶
Creates a new direct chat with specified users and sends the first message.
Parameters:
- string[] usernames
(required): Array of usernames to add to the chat
- string text
(required): Initial message text to send
Returns:
- Task<Chat>
: Response containing the created chat
Example:
try
{
// Get the current authenticated user
GameFuseUser currentUser = GameFuseUser.CurrentUser;
// Create a direct chat with another user
string[] usernames = new string[] { "playerUsername" };
string initialMessage = "Hello! Want to play a game?";
Chat newChat = await currentUser.CreateDirectChatAsync(usernames, initialMessage);
// Access the new chat ID
int chatId = newChat.Id;
Debug.Log($"Direct chat created successfully! Chat ID: {chatId}");
// Access the first message
if (newChat.Messages != null && newChat.Messages.Length > 0)
{
Debug.Log($"First message: {newChat.Messages[0].Text}");
}
}
catch (ApiException ex)
{
Debug.LogError($"Failed to create direct chat: {ex.Message}");
}
CreateGroupChatAsync¶
Creates a new group chat for a specific group and sends the first message.
Parameters:
- int groupId
(required): ID of the group to create a chat for
- string text
(required): Initial message text to send
Returns:
- Task<Chat>
: Response containing the created chat
Example:
try
{
// Get the current authenticated user
GameFuseUser currentUser = GameFuseUser.CurrentUser;
// Create a chat for a specific group
int groupId = 123;
string initialMessage = "Hello group members! Let's coordinate our game strategy.";
Chat groupChat = await currentUser.CreateGroupChatAsync(groupId, initialMessage);
// Access the new chat ID
int chatId = groupChat.Id;
Debug.Log($"Group chat created successfully! Chat ID: {chatId}");
// Access participants
if (groupChat.Participants != null)
{
Debug.Log($"Group chat has {groupChat.Participants.Length} participants");
foreach (ChatParticipant participant in groupChat.Participants)
{
Debug.Log($"Participant: {participant.Username}");
}
}
}
catch (ApiException ex)
{
Debug.LogError($"Failed to create group chat: {ex.Message}");
}
GetMessagesAsync¶
Retrieves a paginated list of messages for a specific chat.
Parameters:
- int chatId
(required): ID of the chat to retrieve messages for
- int page = 1
(optional): Page number for pagination
Returns:
- Task<GetMessagesResponse>
: Response containing messages for the chat
Example:
try
{
// Get the current authenticated user
GameFuseUser currentUser = GameFuseUser.CurrentUser;
// Get messages for a specific chat (first page)
int chatId = 123;
GetMessagesResponse messagesResponse = await currentUser.GetMessagesAsync(chatId);
// Access the messages
ChatMessage[] messages = messagesResponse.Messages;
// Display the messages
Debug.Log($"Retrieved {messages.Length} messages");
foreach (ChatMessage message in messages)
{
Debug.Log($"Message: {message.Text}");
Debug.Log($"From: {message.UserId}, Sent at: {message.CreatedAt}");
Debug.Log($"Read by: {message.ReadBy.Length} users, Current user read: {message.Read}");
}
// To get older messages (next page)
GetMessagesResponse olderMessages = await currentUser.GetMessagesAsync(chatId, 2);
}
catch (ApiException ex)
{
Debug.LogError($"Failed to get messages: {ex.Message}");
}
SendMessageAsync¶
Sends a new message to an existing chat.
Parameters:
- int chatId
(required): ID of the chat to send the message to
- string text
(required): Message text to send
Returns:
- Task<ChatMessage>
: Response containing the sent message
Example:
try
{
// Get the current authenticated user
GameFuseUser currentUser = GameFuseUser.CurrentUser;
// Send a message to an existing chat
int chatId = 123;
string messageText = "Are you ready for the tournament tonight?";
ChatMessage sentMessage = await currentUser.SendMessageAsync(chatId, messageText);
// Access the message ID
int messageId = sentMessage.Id;
Debug.Log($"Message sent successfully! Message ID: {messageId}");
}
catch (ApiException ex)
{
Debug.LogError($"Failed to send message: {ex.Message}");
}
MarkMessageAsReadAsync¶
Marks a specific message as read by the current user.
Parameters:
- int messageId
(required): ID of the message to mark as read
Returns:
- Task<MessageReadResponse>
: Response confirming the message was marked as read
Example:
try
{
// Get the current authenticated user
GameFuseUser currentUser = GameFuseUser.CurrentUser;
// Mark a message as read
int messageId = 456;
MessageReadResponse readResponse = await currentUser.MarkMessageAsReadAsync(messageId);
Debug.Log($"Message marked as read: {readResponse.Message}");
}
catch (ApiException ex)
{
Debug.LogError($"Failed to mark message as read: {ex.Message}");
}
Chat Response Objects¶
Chat¶
The Chat
class contains information about a chat conversation:
Property | Type | Description |
---|---|---|
Id |
int | Chat identifier |
CreatorId |
int | User or group ID that created the chat |
CreatorType |
string | Type of creator (User or Group) |
Messages |
ChatMessage[] | Array of messages in the chat |
Participants |
ChatParticipant[] | Array of chat participants |
ChatMessage¶
The ChatMessage
class contains information about an individual message:
Property | Type | Description |
---|---|---|
Id |
int | Message identifier |
Text |
string | Message content |
UserId |
int | ID of the user who sent the message |
CreatedAt |
string | Timestamp when the message was created |
ReadBy |
string[] | Array of user IDs who have read the message |
Read |
bool | Whether the current user has read the message |
ChatParticipant¶
The ChatParticipant
class extends UserInfo
and contains information about chat participants:
Property | Type | Description |
---|---|---|
IsNewUser |
bool | Whether the user is new to the chat |
(Plus all properties inherited from UserInfo) |
GetChatsResponse¶
The GetChatsResponse
class contains the response from getting chats:
Property | Type | Description |
---|---|---|
DirectChats |
Chat[] | Array of direct chats |
GroupChats |
Chat[] | Array of group chats |
GetMessagesResponse¶
The GetMessagesResponse
class contains the response from getting messages:
Property | Type | Description |
---|---|---|
Messages |
ChatMessage[] | Array of messages |
Common Usage Pattern¶
Here's an example of how to implement a basic chat system in your game:
using UnityEngine;
using GameFuseCSharp;
using System.Linq;
using System.Collections.Generic;
using UnityEngine.UI;
public class ChatManager : MonoBehaviour
{
// UI elements for chat list
[SerializeField] private Transform chatListContainer;
[SerializeField] private GameObject chatItemPrefab;
// UI elements for message display
[SerializeField] private Transform messageContainer;
[SerializeField] private GameObject messageItemPrefab;
[SerializeField] private InputField messageInputField;
[SerializeField] private Button sendMessageButton;
[SerializeField] private Text chatTitleText;
// Current active chat
private int currentChatId = -1;
private string currentChatTitle = "";
private Dictionary<int, List<ChatMessage>> cachedMessages = new Dictionary<int, List<ChatMessage>>();
private void Start()
{
if (sendMessageButton != null)
{
sendMessageButton.onClick.AddListener(HandleSendMessage);
}
}
// Load all chats for the current user
public async void LoadChats()
{
try
{
GameFuseUser currentUser = GameFuseUser.CurrentUser;
if (currentUser == null)
{
Debug.LogError("User not logged in");
return;
}
// Clear existing items
foreach (Transform child in chatListContainer)
{
Destroy(child.gameObject);
}
// Get all chats for the current user
GetChatsResponse response = await currentUser.GetChatsAsync();
// Create UI items for direct chats
foreach (Chat chat in response.DirectChats)
{
GameObject chatItem = Instantiate(chatItemPrefab, chatListContainer);
ChatItemUI chatUI = chatItem.GetComponent<ChatItemUI>();
// Find the other participant(s) for display
string chatName = GetChatDisplayName(chat);
chatUI.SetupChat(chat.Id, chatName, chat);
chatUI.OnChatSelected += SelectChat;
}
// Create UI items for group chats
foreach (Chat chat in response.GroupChats)
{
GameObject chatItem = Instantiate(chatItemPrefab, chatListContainer);
ChatItemUI chatUI = chatItem.GetComponent<ChatItemUI>();
// Use group name for display
string chatName = "Group: " + chat.CreatorId; // You would get the actual group name
chatUI.SetupChat(chat.Id, chatName, chat);
chatUI.OnChatSelected += SelectChat;
}
Debug.Log($"Loaded {response.DirectChats.Length} direct chats and {response.GroupChats.Length} group chats");
}
catch (ApiException ex)
{
Debug.LogError($"Error loading chats: {ex.Message}");
}
}
// Helper method to get a display name for a chat
private string GetChatDisplayName(Chat chat)
{
if (chat.Participants == null || chat.Participants.Length == 0)
{
return "Empty Chat";
}
// For direct chats, show the other participant's name
if (chat.CreatorType == "User")
{
// Find participants who are not the current user
var otherParticipants = chat.Participants.Where(p => p.Id != GameFuseUser.CurrentUser.GetID());
return string.Join(", ", otherParticipants.Select(p => p.Username));
}
// For group chats, could fetch the group name
return "Group Chat";
}
// Select a chat to view
public async void SelectChat(int chatId, string chatName, Chat chatData = null)
{
currentChatId = chatId;
currentChatTitle = chatName;
if (chatTitleText != null)
{
chatTitleText.text = chatName;
}
await LoadMessages(chatId);
}
// Load messages for a selected chat
public async System.Threading.Tasks.Task LoadMessages(int chatId)
{
try
{
GameFuseUser currentUser = GameFuseUser.CurrentUser;
if (currentUser == null)
{
Debug.LogError("User not logged in");
return;
}
// Clear existing messages
foreach (Transform child in messageContainer)
{
Destroy(child.gameObject);
}
// Get messages for the selected chat
GetMessagesResponse response = await currentUser.GetMessagesAsync(chatId);
// Cache the messages
if (!cachedMessages.ContainsKey(chatId))
{
cachedMessages[chatId] = new List<ChatMessage>();
}
else
{
cachedMessages[chatId].Clear();
}
// Add messages to cache
cachedMessages[chatId].AddRange(response.Messages);
// Create UI items for each message
DisplayMessages(chatId);
// Mark all messages as read
foreach (ChatMessage message in response.Messages)
{
if (!message.Read)
{
await currentUser.MarkMessageAsReadAsync(message.Id);
}
}
}
catch (ApiException ex)
{
Debug.LogError($"Error loading messages: {ex.Message}");
}
}
// Display cached messages for a chat
private void DisplayMessages(int chatId)
{
if (!cachedMessages.ContainsKey(chatId) || cachedMessages[chatId].Count == 0)
{
return;
}
foreach (ChatMessage message in cachedMessages[chatId])
{
GameObject messageItem = Instantiate(messageItemPrefab, messageContainer);
MessageItemUI messageUI = messageItem.GetComponent<MessageItemUI>();
bool isFromCurrentUser = message.UserId == GameFuseUser.CurrentUser.GetID();
messageUI.SetupMessage(message.Text, message.CreatedAt, isFromCurrentUser);
}
// Scroll to bottom (you'd need to implement this based on your UI)
ScrollToBottom();
}
// Send a new message
public async void HandleSendMessage()
{
if (currentChatId < 0)
{
Debug.LogWarning("No chat selected");
return;
}
string messageText = messageInputField.text;
if (string.IsNullOrEmpty(messageText))
{
return;
}
try
{
GameFuseUser currentUser = GameFuseUser.CurrentUser;
if (currentUser == null)
{
Debug.LogError("User not logged in");
return;
}
// Send the message
ChatMessage sentMessage = await currentUser.SendMessageAsync(currentChatId, messageText);
// Clear the input field
messageInputField.text = "";
// Add the new message to cache
if (cachedMessages.ContainsKey(currentChatId))
{
cachedMessages[currentChatId].Add(sentMessage);
// Create UI for the new message
GameObject messageItem = Instantiate(messageItemPrefab, messageContainer);
MessageItemUI messageUI = messageItem.GetComponent<MessageItemUI>();
messageUI.SetupMessage(sentMessage.Text, sentMessage.CreatedAt, true);
// Scroll to bottom
ScrollToBottom();
}
Debug.Log($"Message sent: {sentMessage.Text}");
}
catch (ApiException ex)
{
Debug.LogError($"Error sending message: {ex.Message}");
}
}
// Create a new direct chat
public async void CreateDirectChat(string username)
{
try
{
GameFuseUser currentUser = GameFuseUser.CurrentUser;
if (currentUser == null)
{
Debug.LogError("User not logged in");
return;
}
// Create a direct chat
string[] usernames = new string[] { username };
string initialMessage = "Hello! I'd like to chat.";
Chat newChat = await currentUser.CreateDirectChatAsync(usernames, initialMessage);
// Refresh the chat list
LoadChats();
// Select the new chat
SelectChat(newChat.Id, username, newChat);
Debug.Log($"Created new direct chat with {username}");
}
catch (ApiException ex)
{
Debug.LogError($"Error creating direct chat: {ex.Message}");
}
}
// Create a new group chat
public async void CreateGroupChat(int groupId, string groupName)
{
try
{
GameFuseUser currentUser = GameFuseUser.CurrentUser;
if (currentUser == null)
{
Debug.LogError("User not logged in");
return;
}
// Create a group chat
string initialMessage = "Hello everyone! I've created a group chat for us.";
Chat newChat = await currentUser.CreateGroupChatAsync(groupId, initialMessage);
// Refresh the chat list
LoadChats();
// Select the new chat
SelectChat(newChat.Id, "Group: " + groupName, newChat);
Debug.Log($"Created new group chat for group {groupName}");
}
catch (ApiException ex)
{
Debug.LogError($"Error creating group chat: {ex.Message}");
}
}
// Helper method to scroll the message view to the bottom
private void ScrollToBottom()
{
// Implement based on your UI components
// For example, if using a ScrollRect:
// messageScrollRect.verticalNormalizedPosition = 0f;
}
}
// UI component for displaying chat items in a list
public class ChatItemUI : MonoBehaviour
{
[SerializeField] private Text chatNameText;
[SerializeField] private Text lastMessageText;
[SerializeField] private Button chatButton;
private int chatId;
private string chatName;
private Chat chatData;
// Event for when this chat is selected
public System.Action<int, string, Chat> OnChatSelected;
private void Start()
{
if (chatButton != null)
{
chatButton.onClick.AddListener(OnChatClicked);
}
}
public void SetupChat(int id, string name, Chat data)
{
chatId = id;
chatName = name;
chatData = data;
if (chatNameText != null)
{
chatNameText.text = name;
}
if (lastMessageText != null && data.Messages != null && data.Messages.Length > 0)
{
// Show the latest message
ChatMessage latestMessage = data.Messages[0];
string sender = latestMessage.UserId == GameFuseUser.CurrentUser.GetID() ? "You" : "Other";
lastMessageText.text = $"{sender}: {latestMessage.Text}";
}
else if (lastMessageText != null)
{
lastMessageText.text = "No messages yet";
}
}
private void OnChatClicked()
{
OnChatSelected?.Invoke(chatId, chatName, chatData);
}
}
// UI component for displaying message items
public class MessageItemUI : MonoBehaviour
{
[SerializeField] private Text messageText;
[SerializeField] private Text timestampText;
[SerializeField] private RectTransform messageContainer;
public void SetupMessage(string text, string timestamp, bool isFromCurrentUser)
{
if (messageText != null)
{
messageText.text = text;
}
if (timestampText != null && !string.IsNullOrEmpty(timestamp))
{
// Format the timestamp
if (System.DateTime.TryParse(timestamp, out System.DateTime dateTime))
{
timestampText.text = dateTime.ToString("HH:mm");
}
else
{
timestampText.text = timestamp;
}
}
// Align the message based on sender
if (messageContainer != null)
{
// You would implement this based on your UI layout
// For example:
/*
if (isFromCurrentUser)
{
messageContainer.anchorMin = new Vector2(1, 0);
messageContainer.anchorMax = new Vector2(1, 0);
messageContainer.pivot = new Vector2(1, 0);
messageContainer.anchoredPosition = new Vector2(-10, 0);
messageBackground.color = currentUserBubbleColor;
}
else
{
messageContainer.anchorMin = new Vector2(0, 0);
messageContainer.anchorMax = new Vector2(0, 0);
messageContainer.pivot = new Vector2(0, 0);
messageContainer.anchoredPosition = new Vector2(10, 0);
messageBackground.color = otherUserBubbleColor;
}
*/
}
}
}
Error Handling¶
All chat methods throw an ApiException
when a request fails. Always wrap your API calls in try-catch blocks to handle errors gracefully.
Common errors include: - User not found (when creating a direct chat) - Chat not found (when sending messages) - Insufficient permissions - Network connectivity issues