Unread Chat Messages #

This guide demonstrates how to retrieve the latest unread chat messages in a specific chat channel for your player, and get the total number of unread messages which can be displayed in the game UI.

Displaying an unread message count in the game UI
Displaying an unread message count in the game UI

Joining the channel #

You need to join the appropriate chat channel in order to start retrieving messages. The following example joins a room channel called global-chat.

1
2
var channel = await Socket.JoinChatAsync("global-chat", ChannelType.Room, true);
var channelId = channel.Id;

Cacheable cursor #

Nakama’s cacheable cursors can be used to store a reference to where in the channel history you last read up to. This value can be stored in Unity’s PlayerPrefs.

Retrieve the cacheable cursor, defaulting to an empty string if it doesn’t already exist.

1
2
const string MESSAGES_CURSOR = "MESSAGES_CURSOR";
var messagesCursor = PlayerPrefs.GetString(MESSAGES_CURSOR, string.Empty);

Use the cacheable cursor to retrieve messages from where you left off. The following will retrieve the next 100 messages from the given cursor.

1
2
3
var limit = 100;
var forward = true;
var messageList = await Client.ListChannelMessagesAsync(Session, channel.Id, limit, forward, messagesCursor);

Retrieving all unread messages #

The above example only gets up to 100 new messages, but you may want to get all new messages and display a total unread message count.

To do this you need to make several calls to the ListChannelMessageAsync function, passing in an updated cursor each time. How many calls you need to make depends on the limit you set and the total number of remaining unread messages, but walking the history this way is fast.

Using a while loop you can retrieve unread messages in batches of 100, updating the cursor each time and ending once the ListChannelMessagesAsync method returns no more messages.

When all messages have been retrieved you should update the cacheable cursor value in PlayerPrefs to ensure that it is correct for the next time you perform this logic.

Below is a full example of a GetUnreadMessages method.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
private async Task<IList<IApiChannelMessage>> GetUnreadMessages(string channelId, int batchSize = 100)
{
    // Create an empty list to store unread messages
    var unreadMessages = new List<IApiChannelMessage>();

    // Get the current value of the cacheable cursor from PlayerPrefs
    var messagesCursor = PlayerPrefs.GetString(MESSAGES_CURSOR, string.Empty);

    var done = false;
    while (!done)
    {
        // Retrieve the next 100 messages
        var messageList = await Client.ListChannelMessagesAsync(Session, channelId, batchSize, true, messagesCursor);

        // Add the messages to the unreadMessages list
        unreadMessages.AddRange(messageList.Messages);

        // Update the cursor ready for the next iteration
        messagesCursor = messageList.CacheableCursor;
        
        // Get the number of messages retrieved this iteration
        var messageCount = messageList.Messages.Count();
        Debug.Log($"Got {messageCount} messages.");
        
        // If the message count this iteration matched the batch size, there may be more messages to get so continue
        if (messageCount == batchSize)
        {
            Debug.Log("Attempting to get more messages.");
            continue;
        }
        
        // If we reached this point, there are no more messages
        // Update the cacheable cursor stored in PlayerPrefs
        PlayerPrefs.SetString(MESSAGES_CURSOR, messagesCursor);

        // We're done
        Debug.Log($"Finished getting a total of {unreadMessages.Count} messages.");
        done = true;
    }
    
    // Return the list of unread messages
    return unreadMessages;
}

This function can be called whenever you need to update your game’s UI.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
var channelId = "<SomeChannelId>";
var batchSize = 100;

var unreadMessages = await GetUnreadMessages(channelId, batchSize);
UnreadMessagesText.text = $"You have {unreadMessages.Count} unread messages.";

foreach (var unreadMessage in unreadMessages)
{
    // Add unreadMessage.Content to chat log as appropriate
}