11 min read
.
on Feb 12, 2021
How to build a multiplayer, in-game chat room with Unity and PubNub, allowing multiple users to chat in real time.

Real-time player communication is essential for an engaging gaming experience. When players chat with their friends and other gamers, they are more likely to keep returning to your game. Multiplayer game experiences are often the most difficult part of game development in Unity.

One key problem for game developers is that multiplayer chat can’t be a priority because game developers are focused on building the best game possible to differentiate themselves in the market. With PubNub, building real-time experiences is significantly easier because it allows you to cut out the work of building a backend. Your focus will be entirely on building your game.

PubNub Unity SDK

Using the PubNub Unity SDK, game developers can easily build chat and games without having to sacrifice a large amount of time learning, creating, and managing the mechanics behind sending chat messages or player data in real time. PubNub manages all of the scaling and infrastructure for you and provides easy-to-use API’s so your game "just works." With PubNub, you can focus on the front-end of your game without worrying about the infrastructure behind it.

Unity sample chat app demo

Start this tutorial by opening the Unity sample chat app demo
Before beginning this tutorial, be sure to open the demo in two or more windows.

Open the Unity sample chat app demo

In this tutorial, you’ll be building a real-time multiplayer chat lobby in Unity with PubNub, which is used to send and receive messages between players. This tutorial forms the basis for building common chat scenarios in gaming like game-wide chat, team chat, or private chat. Open the demo in two or more windows to simulate transmitting messages in real time between players in the game lobby. Export the demo app to any device or platform Unity supports, and you’ll still be able to send messages between players in real time. 

Unity multiplayer real-time chat room tutorial

Since Unity is cross-platform, game developers can reach a lot of players in a lot of places from one application. This multiplies the potential for real-time multiplayer experiences, however it comes at the risk of your game growing faster than expected. Your backend infrastructure will not be able to handle the rapid change in load. With PubNub’s Unity SDK, you only need to write front-end code because PubNub manages and scales the infrastructure for you. You’re able to use PubNub to power your entire game, not only chat. If you use PubNub to power all of your real-time actions, then your entire game can be built without a backend (aside from PubNub). The risk of server downtime and your game being unreachable is mitigated if your game grows faster than expected while using PubNub.

If your game frequently has live events with large surges of players, PubNub will work for your game. PubNub has been proven to work with applications that experience a large fluctuation in the amount of activity on a day-to-day basis. In the game industry, being able to focus totally on your game while having complete faith in your infrastructure is incredibly important and difficult to achieve. With PubNub Unity SDK you’re able to create real-time games and experiences with ease.  

In this tutorial, you will learn how to build a real-time multiplayer game chat lobby using Unity 3D and PubNub. Export this chat application to iOS, Android, Web, AR/VR, video game consoles, or any other platform Unity exports to and gamers will be able to play and chat across platforms. Gamers can chat in real time, and you can even playback messages to users who were offline or busy when the messages were sent.  

A free PubNub account has all the features you need to build the real-time chat lobby in this tutorial. Once you sign up, get your unique PubNub keys from the PubNub Admin Dashboard. With PubNub you won’t need any other backend for building the chat features covered here. Focus on the front-end of your game and use PubNub API’s for your game backend. 

Unity environment setup

Before you begin, you’ll need to download the Unity Hub. The Unity Hub is used to manage Unity versions and Unity projects you’re developing. 

Once you’ve downloaded Unity Hub, add any Unity Version equal to or older than 2018 LTS. The 2018 LTS version was used to create the tutorial app, but upgrade it if you wish. 

Unity project setup

There are two ways to follow this tutorial: by creating a new chat project from scratch or by downloading the tutorial repo and following along. Downloading the Unity chat tutorial repo is the faster way to get started.

Getting started building a new Unity chat lobby project

You only need to do these steps if you are creating a new project in Unity Hub to build real-time multiplayer chat. Create a new project by opening Unity Hub, go to the projects tab, and click ‘NEW’. Configure the project how you’d like. 

You’ll need to import the PubNub SDK into your Unity Chat project. Download the latest version of the PubNub Unity SDK package. Then import that package into your Unity project by going to Assets > Import Package > Custom Package. 

You’ll need to import the PubNub SDK into your Unity Chat project. Download the latest version of the PubNub Unity SDK package. Then import that package into your Unity project by going to Assets > Import Package > Custom Package. 

When you import the package you may get a bunch of error messages. We’ll take care of that in the next step.

Importing unity chat tutorial repo

Download or clone the Unity chat tutorial repo. Open Unity Hub, go to the projects tap, and click ‘ADD’. 

If you’re using a Unity version newer than 2018 LTS then you’ll be asked to confirm you want to upgrade the project to a newer version of Unity. Upgrading the project may break the exact location of some UI elements, however the app will still work and the UI objects can be repositioned. Click ‘Confirm’ to continue.

When you import the project you may get a bunch of error messages. We’ll take care of that in the next step.

‘TestTools does not exist’ errors in Unity

After importing the PubNub SDK or the tutorial project, you might see an error message in the Unity console window that looks like this:

error CS0234: The type or namespace name 'TestTools' does not exist…

Fix the error by going to Window > General > Test Runner. Click on the drop-down menu in the top right corner and enable playmode tests for all assemblies. Close all open Unity windows completely and reopen your project.

Unity sample app: Enable playmode tests for all assemblies

Unity chat room UI

If you downloaded the Unity chat tutorial example project, there will be 4 key folders in the repo: Assets, PubNub, Scenes and Scripts. 

In the Assets folder, there is a background image, submit button, font files and a loading circle. 

In the Scripts folder, there are the two scripts: SendMessage and LoadingCircle. The SendMessage script is where we will be writing the code to send and receive messages from clients in real time. If you’re building the project yourself from scratch, you’ll need to create the SendMessage script. 

Open the scenes/RealtimeChat scene by clicking on the scene in the Unity project navigator. The RealtimeChat scene includes a Main Camera and a Canvas.

The Canvas renders all of the input fields, buttons, and text. There is also a background image and a line to separate the bottom and top sections of the screen.

If you create the project from scratch, you will need to create a Main Camera and attach a SendMessage script to it. Design your chat application user interface however you’d like.

In the Unity chat tutorial example project, the input fields and a send button are placed at the bottom of the screen. Messages are displayed in a list that’ll appear in the center of the screen. Messages are removed from the displayed list when it is full.

Building real-time chat system functionality

First, require the PubNub API and the other UnityEngine libraries. The JSONInformation class will be used to format input data to publish to PubNub.

The SendMessage class is where the logic for the chat messaging will happen. At the start of the SendMessage class we’ll instantiate public variables used by the app and create a chatMessageQueue to manage creating and deleting messages from the UI.

This is what the script looks like so far:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PubNubAPI;
using UnityEngine.UI;
public class JSONInformation
{
    public string username;
    public string text;
}

public class SendMessage : MonoBehaviour {
    public static PubNub pubnub;
    public Font customFont;
    public Button SubmitButton;
    public Canvas canvasObject;
    public InputField UsernameInput;
    public InputField TextInput;
    public int counter = 0;
    public int indexcounter = 0;
    public Text deleteText;
    public Text moveTextUpwards;
    private Text text;

    Queue<GameObject> chatMessageQueue = new Queue<GameObject>();
   
    void Start(){

    }

    void CreateChat(JSONInformation payLoad){

    }

    void SyncChat() {
       
    }

    void Update () {

After creating public variables, go back to the Unity inspector and drag each element from the project hierarchy to the appropriate field on the SendMessage script. It should look like this:

Unity send message script

Now let's create the Start() function. You’ll need free API keys from PubNub to continue:

  1. Sign up for a PubNub account

  2. Go to your PubNub Dashboard.

  3. Click Create New App.

  4. Give your app a name, and select Chat App as the app type.

  5. Click Create.

  6. Click your new app to open its settings, then click its keyset.

  7. Enable the Storage and Playback feature for your keyset. 

  8. Save the changes.

  9. Copy the Publish and Subscribe keys for the next steps.

Now that you have API keys, initialize PubNub and create a listener on the button that will run the TaskOnClick() function when pressed. Then, get the last 12 messages that were sent on the PubNub Channel ‘chatchannel’ (change this name if you want) using the PubNub Storage and Playback API. 

Change “YOUR-PUBLISH-KEY-HERE” and “YOUR-SUBSCRIBE-KEY-HERE“ to the API keys from your PubNub dashboard. 

If there is an error getting the messages from PubNub, then print the error in the Unity console. Otherwise, iterate through the last 12 messages and load them into the class JSONInformation. Then, call the function CreateChat() and pass the message to that function to display the data on the screen.

Additionally, create a counter for formating the messages on screen. This way messages aren't created past the black line. 

Then, we subscribe to the PubNub channel ‘chatchannel’.  The subscribe callback function is triggered when a message is published on that channel. The callback takes the data from the channel event, writes it to the end of the chat history for UI display, and removes the oldest message if there are more than 12.

void Start()
    {
        // Use this for initialization
        PNConfiguration pnConfiguration = new PNConfiguration();
        pnConfiguration.PublishKey = "YOUR-PUBLISH-KEY-HERE";
        pnConfiguration.SubscribeKey = "YOUR-SUBSCRIBE-KEY-HERE";
        pnConfiguration.LogVerbosity = PNLogVerbosity.BODY;
        pnConfiguration.UUID = System.Guid.NewGuid().ToString();
        pubnub = new PubNub(pnConfiguration);

        // Add Listener to Submit button to send messages
        Button btn = SubmitButton.GetComponent<Button>();
        btn.onClick.AddListener(TaskOnClick);

        // Fetch the last 12 messages sent on the given PubNub 
channel
        pubnub.FetchMessages()
            .Channels(new List<string> { "chatchannel" })
            .Count(12)
            .Async((result, status) =>
            {
            if (status.Error)
            {
                Debug.Log(string.Format(
                    " FetchMessages Error: {0} {1} {2}", 
                    status.StatusCode, status.ErrorData, status.Category
                ));
            }
            else
            {
                foreach (KeyValuePair<string, List<PNMessageResult>> kvp in result.Channels)
                {
                    foreach (PNMessageResult pnMessageResult in kvp.Value)
                    {
                        // Format data into readable format
                        JSONInformation chatmessage = JsonUtility.FromJson<JSONInformation>(pnMessageResult.Payload.ToString());

                        // Call the function to display the message in plain text
                        CreateChat(chatmessage);

                        // Counter used for positioning the text UI 
                        if (counter != 650)
                        {
                            counter += 50;

void Start()
    {
        // Use this for initialization
        PNConfiguration pnConfiguration = new PNConfiguration();
        pnConfiguration.PublishKey = "YOUR-PUBLISH-KEY-HERE";
        pnConfiguration.SubscribeKey = "YOUR-SUBSCRIBE-KEY-HERE";
        pnConfiguration.LogVerbosity = PNLogVerbosity.BODY;
        pnConfiguration.UUID = System.Guid.NewGuid().ToString();
        pubnub = new PubNub(pnConfiguration);

        // Add Listener to Submit button to send messages
        Button btn = SubmitButton.GetComponent<Button>();
        btn.onClick.AddListener(TaskOnClick);

        // Fetch the last 12 messages sent on the given PubNub channel
        pubnub.FetchMessages()
            .Channels(new List<string> { "chatchannel" })
            .Count(12)
            .Async((result, status) =>
            {
            if (status.Error)
            {
                Debug.Log(string.Format(
                    " FetchMessages Error: {0} {1} {2}", 
                    status.StatusCode, status.ErrorData, status.Category
                ));
            }
            else
            {
                foreach (KeyValuePair<string, List<PNMessageResult>> kvp in result.Channels)
                {
                    foreach (PNMessageResult pnMessageResult in kvp.Value)
                    {
                        // Format data into readable format
                        JSONInformation chatmessage = JsonUtility.FromJson<JSONInformation>(pnMessageResult.Payload.ToString());

                        // Call the function to display the message in plain text
                        CreateChat(chatmessage);

                        // Counter used for positioning the text UI 
                        if (counter != 650)
                        {
                            counter += 50;
                        }
                    }
                 }
             }
             });

        // Subscribe to a PubNub channel to receive messages when they are sent on that channel
        pubnub.Subscribe()
            .Channels(new List<string>() {
                "chatchannel"
            })
            .WithPresence()
            .Execute();

        // This is the subscribe callback function where data is recieved that is sent on the channel
        pubnub.SusbcribeCallback += (sender, e) =>
        {
            SusbcribeEventEventArgs message = e as SusbcribeEventEventArgs;
            if (message.MessageResult != null)
            {
                // Format data into a readable format
                JSONInformation chatmessage = JsonUtility.FromJson<JSONInformation>(message.MessageResult.Payload.ToString());

                // Call the function to display the message in plain text
                CreateChat(chatmessage);

                // When a new chat is created, remove the first chat and transform all the messages on the page up
                SyncChat();

                // Counter used for position the text UI
                if (counter != 650)
                {
                    counter += 50;
                }
            }
        };
    }


After creating the start() function, let's create the CreateChat() function that will place new text objects onto the scene whenever the function is called.

The message information from the subscribe is passed to the function and is assigned to the ChatMessage object’s text. Additionally, the message is added to the queue and the index counter is iterated.

// Function used to create new chat objects based of the data received from PubNub
void CreateChat(JSONInformation payLoad){
  // Create a string with the username and text
  string currentObject = string.Concat(payLoad.username, payLoad.text);

  // Create a new gameobject that will display text of the data sent via PubNub
  GameObject chatMessage = new GameObject(currentObject);
  chatMessage.transform.SetParent(canvasObject.GetComponent<Canvas>().transform);
 chatMessage.AddComponent<Text>().text = currentObject;

  // Assign text to the gameobject. Add visual properties to text
  var chatText = chatMessage.GetComponent<Text>();
  chatText.font = customFont;
  chatText.color = UnityEngine.Color.black;
  chatText.fontSize = 18;

  // Assign a RectTransform to gameobject to manipulate positioning of chat.
  RectTransform rectTransform;
  rectTransform = chatText.GetComponent<RectTransform>();
  rectTransform.localPosition = new Vector2(-10, 430 - counter);
  rectTransform.sizeDelta = new Vector2(650, 50);
  rectTransform.localScale = new Vector3(1F, 1F, 1F);

  // Assign the gameobject to the queue of chat messages
  chatMessageQueue.Enqueue(chatMessage);

  // Keep track of how many objects we have displayed on the screen
  indexcounter++;
}

Now that there’s a CreateChat() function, we can add functionality that moves all displayed messages up on the screen and deletes the first (top) message on the screen to make room for a new message.

void SyncChat() {
  // If more 12 objects are on the screen, we need to start removing them
  if (indexcounter > 12)
  {
      // Delete the first gameobject in the queue
      GameObject deleteChat = chatMessageQueue.Dequeue();
      Destroy(deleteChat);

      // Move all existing text game objects up
foreach (GameObject moveChat in chatMessageQueue)
      {
          RectTransform moveText = moveChat.GetComponent<RectTransform>();
          moveText.offsetMax = new Vector2(moveText.offsetMax.x, moveText.offsetMax.y + 50);
      }
  }
}

The final step to building a Unity player chat lobby is adding the functionality for players to send messages. When a player clicks the submit button, the text should be formatted and published through PubNub. When a message is published, all open clients should receive and display the message. 

Don’t forget to clear the input field after a new message is submitted.

 // create a JSON object from input field input
  JSONInformation publishMessage = new JSONInformation();
  publishMessage.username = string.Concat(UsernameInput.text, ": ");
  publishMessage.text = TextInput.text;
  string publishMessageToJSON = JsonUtility.ToJson(publishMessage);

  // Publish the JSON object to the assigned PubNub Channel
  pubnub.Publish()
      .Channel("chatchannel")
      .Message(publishMessageToJSON)
      .Async((result, status) =>
      {
          if (status.Error)
          {
              Debug.Log(status.Error);
              Debug.Log(status.ErrorData.Info);
          }
          else
          {
           // Debug.Log(string.Format("Publish Timetoken: {0}", result.Timetoken));
          }
      });

  TextInput.text = "";
}

Save your work in the Unity editor. Build and run by clicking the “play” button. You should now be able to send and receive messages from your Unity Chat lobby. It’s really that simple to make a real-time chat application in the Unity 3D game engine with PubNub!

This Blog is part of our Developer Path for Unity - Discover, Explore, Build, and expand your unity knowledge all in one place.

More resources for adding chat to your Unity game

PubNub offers a powerful real-time network and APIs to send and receive data in any application. Take advantage of PubNub services to easily build chat with enterprise-grade security, scalability, and reliability. PubNub eliminates the time it takes to set up and manage your infrastructure so you’re enabled to focus on building the next blockbuster game.

Learn more about PubNub and Gaming with these great resources:

Have suggestions or questions about the content of this post? Reach out to our team of experts.

More From PubNub