How to Build Realtime Chat with Unity


Scroll down to start the step by step tutorial

</> Demo our Sample Unity Chat App

The Unity chat lobby shown here is an example of what you’ll be building with this tutorial. Open the demo in two or more windows to simulate transmitting messages in realtime 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 realtime. PubNub powers this realtime communication between clients and will work on all devices and platforms that Unity exports too.

Using PubNub with Unity is so easy that this code is all you need to publish a new chat message:

void TaskOnClick()
    {
        // When the user clicks the Submit button,
        // 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(result.Timetoken));
                }
            });

        // Reset the text field to be blank
        TextInput.text = "";
    }

Cloning the GitHub Project

Create a new chat project from scratch or download the tutorial repo and follow along.

Cloning the Unity chat tutorial repo and following along is the faster way to get started.

git clone https://github.com/pubnub/Unity-Realtime-Chat-Room-Tutorial.git

Unity Multiplayer Chat Lobby Tutorial

Unity is a cross-platform game engine open to the developer community, enabling the building and publishing of content created within the game engine. Unity is easy to use, but creating multiplayer games and experiences has always been one of the most challenging hurdles on the platform. Using PubNub with Unity enables creating realtime multiplayer games significantly easier.

PubNub empowers developers to build low-latency, realtime applications that perform reliably and securely, at a global scale. All developers need to do is write the front-end code with PubNub's easy-to-use API's and PubNub handles all the infrastructure for you. This is especially important in the game development industry, as it mitigates the risk of multiplayer server downtime in the event that your game grows faster than expected.

In this tutorial, we'll walk through how to build a basic multiplayer game lobby chat room using the Unity 3D game engine. This tutorial will work across iOS, Android, AR/VR, Web, and Video Game Consoles. No matter what platform you are exporting to all users will be able to chat between devices. PubNub can also power the realtime interactions between players in your game and not just chat. This makes the possibilities endless with the PubNub API and Unity for game development.

Step 1: Unity and Unity Hub Setup

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.

Step 2: Environment and Project Setup

Create a new project by opening Unity Hub, go to the projects tap, and click ‘NEW’. Configure the project how you’d like. Then import the PubNub SDK into your Unity project. Do so by downloading the latest PubNub.unitypackage. Import that package into Unity by going to Assets -> Import Package -> Custom Package.

Once imported there may be errors in your console window. You may see:

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

Fix this problem 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.

Note: If you download or clone the GitHub repo, you won't have to re-import the PubNub package. You will only have to enable the Test Runner. Download the Unity Chat lobby repo here.


The GitHub repo includes four folders. 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 realtime.

Step 3: Building the UI

In your applications hierarchy, there are a few essential elements that display chat messages on the screen. The RealtimeChat Scene includes a Main Camera, and a Canvas that renders all of the input fields, buttons, and text objects on the screen. In order for the input fields to be interactive, an EventSystem object is automatically created and displayed in the Hierarchy. Additionally, there are assets such as a background, which is a simple PNG; and a line to separate the bottom and top sections of the screen.

If you are starting the project from scratch, you will need to create a Main Camera, which should have the SendMessage script attached to it.


Design your user interface however you would like. In the Unity Chat Tutorial example app the loadingCircle is placed on the top right of the screen, and the input fields at the bottom of the screen with the submit button. The chat messages will appear in the middle of the screen and will be removed from the UI once the screen is completely full of messages.


Now that the scene has been designed, let's add a script to the Main Camera to develop the chat room interface for the application.

Step 4: Developing the Realtime Chatroom Functionality

TThe first step is to require the PubNub API and other UnityEngine libraries, including UnityEngine.ui. The class JSONInformation is where input field data will be formatted to be published via PubNub.

The class SendMessage is where all of the application’s chatroom logic will be written. We start off by creating some public variables and creating a chatMessageQueue to handle message creation and deletion.

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 () {

    }
    void TaskOnClick(){

    }
}

Now that you have created your public variables, make sure to return to your Unity Inspector and drag each element from your Hierarchy into the appropriate fields on your SendMessage Script.

Next, let's create the Start() function. First fill out and submit the form below to generate your own PubNub Publish and Subscribe keys: you will need them in order to get your application to publish and receive messages.

In the beginning of the Start() function, initialize PubNub and create a listener on the button that will run the TaskOnClick() function when pressed. Next, fetch the last 12 messages that were sent on the PubNub Channel "chatchannel" (name this channel whatever you wish). If there is an error, print the error in the Unity console, however if there isn't one, iterate through the last 12 messages and insert them into the class JSONInformation. Then run the function CreateChat() and pass the chat message to that function to print the data on the screen.

Create a counter for formating the messages on screen so that messages aren't created past the black line. Next, we subscribe to the PubNub channel "chatchannel". When an event is published on that channel it will trigger the subscribe callback function. The callback takes the value from the channel event, writes it to the end of the chat history for view, and removes the oldest message if there are more than 12 (ensuring no more than 12 messages are on screen at the same time)

void Start()
    {
        // Use this for initialization
        PNConfiguration pnConfiguration = new PNConfiguration();
        pnConfiguration.PublishKey = "YOUR-PUBLISH-KEY-HERE";
        pnConfiguration.SubscribeKey = "YOUR-SUBSCRIBE-KEYS-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;
                }
            }
        };
    }

Next, let's create the CreateChat function which will be responsible for placing new text objects onto the screen whenever the function is called. The payload information from the PubNub subscribe is passed through the function, and then is assigned to the text 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 = 35;

  // Assign a RectTransform to gameobject to maniuplate 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 chatmessages
  chatMessageQueue.Enqueue(chatMessage);

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

Now that the CreateChat() function has been created, we’ll add functionality that translates all existing messages up on the screen to make room for the new message. Additionally, let's delete the first message on the screen to make room for the 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 gameobjects up the Y axis 50 pixels
      foreach (GameObject moveChat in chatMessageQueue)
      {
          RectTransform moveText = moveChat.GetComponent<RectTransform>();
          moveText.offsetMax = new Vector2(moveText.offsetMax.x, moveText.offsetMax.y + 50);
      }
  }
}

The final step is to add the functionality that allows a user to send a message and reset the text field to be blank once the message has been submitted. In clicking the submit button, the user is publishing the message through PubNub. When a message is published, all subscribed clients with the application open will receive that message in realtime.

void TaskOnClick()
{
  // When the user clicks the Submit button,
  // 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 and click the “run” button. You should now be able to send and receive messages from your Unity Chat lobby. It's really that easy to make your first realtime chat application in the Unity 3D game engine.

If you ran into any roadblocks with the tutorial, feel free to reach out at sales@pubnub.com. Download the source code here!

Share