Nowadays online chats are an important part of everyday life. From a multiplayer game all the way to Whatsapp, Twitch and Discord, a chat is an integral feature of so many online services.

For this reason I wanted to try and write a basic chat in Unity3D. I will use this as a starting point and keep building on top of it. I want to experiment with different server infrastructures in the future.

Turns out that the Unity HLAPI makes this process surprisingly simple! Let’s have a look.

Setting up your scene

Since this was to be a simple project, I decided to go with just one scene which I have called Main. In the main scene there are two important game objects.

  • Network Manager
  • UIChat

The Network Manager will be responsible for the creation and destruction of game objects. While the UIChat will be used as a helper to display the chat as the players type in their messages.

Network Manager Setup

We need to set-up a couple of things in the Network Manager, since it will be responsible for spawning game objects over the network.

First of all, we need to register a player object to be spawned when a player connects. For this, I have created a prefab called PlayerChat and reference it in the Network Manager inspector under Spawn Info –> Player Prefab field. I will explain what PlayerChat does in a moment.

I also created a prefab, called UIChatEntry which I’m going to use to represent a single chat message. The prefab needs to be registered to the Network Manager as well.

Note that all these objects have a Network Identity component attached, which is used by the Network Manager for Creation and destruction of such objects.

PlayerChat.cs

PlayerChat is the game object which represents the user within the chat and there is going to be one of these game objects per user.

public class PlayerChat : NetworkBehaviour
{
    [SyncVar]
    public Color playerColor = new Color();
}

You will notice that PlayerChat is a NetworkBehaviour. This is because we are going to have network functionality within the class.
The second thing you’ll notice is the SyncVar attribute on top of the playerColor variable. The Network Manager is only responsible for the creation and destruction of networked game objects: this means that it leaves the state synchronisation up to us. SyncVar does exactly that, it syncs playerColor across all PlayerChat instances on the network. This way I can have a different colour per user, and that user will have the same colour on all other clients. That is, if I’m a user with a Red colour, all the other clients connected to the chat will see me as Red.

    public override void OnStartClient()
    {
        base.OnStartClient();

        chat = FindObjectOfType<UIChat&gt;();
        chat.sendButton.onClick.AddListener( OnSendButton );
        playerColor = new Color( Random.Range( 0, 256 ) / 256f, Random.Range( 0, 256 ) / 256f, Random.Range( 0, 256 ) / 256f );

        Debug.Log( "Client" );
    }
    
    public override void OnStartLocalPlayer()
    {
        base.OnStartLocalPlayer();

        CmdSendChatMessage( "New Client joined chat... say hello! \n" );

        Debug.Log( "Local Player" );
    }

    [Command]
    private void CmdSendChatMessage( string inMessage )
    {
        if ( !string.IsNullOrEmpty( inMessage ) )
        {
            chat.CreateChatEntry( inMessage, playerColor );

            Debug.Log( "Received Message " + inMessage );
        }
    }

OnStartClient is called in all instances when a Player Object is created. I’m using this method to hook up a reference to the UIChat object and to determine the colour of the player.

OnStartLocalPlayer is then called only in the instance that represents the local user. This is useful since we want to send the Welcome Message only once, when the user logs into the chat. Since there are going to be multiple PlayerChat objects, it is very useful to have a method that identifies the local user only.

To send a Chat message we call the CmdSendChatMessage method with a string representing the message. This method has the Command attribute above it. The attribute is used to invoke a method on the server from a client. When the server invokes this method, it calls UIChat to instantiate a UIChatEntry for the chat message. The UIChatEntry will then be created on all clients.

UIChat.cs

    public void CreateChatEntry( string message, Color inPlayerColor )
    {
        UIChatEntry chat = GameObject.Instantiate( chatPrefab ).GetComponent<UIChatEntry&gt;();

        chat.ShowMessage( message, inPlayerColor );
        PositionEntryInGrid( chat.gameObject );

        NetworkServer.Spawn( chat.gameObject );
    }

This class is simply used to display the chat messages by instantiating a UIChatEntry and then calling NetworkServer.Spawn. The Spawn method is used to create game objects over the network. The Server will serialise the UIChatEntry instance and send its data to the clients, which will, in turn, deserialise it and create their own copy of that instance.

UIChatEntry itself is a very simple class which just contains a player’s colour and the message to show.

public class UIChatEntry : NetworkBehaviour
{
    public Text chatText = null;
    public Image backing = null;

    [SyncVar]
    string text = null;
    [SyncVar]
    Color color = new Color();
}

Test the project

In order to test the project you will need 2 players chatting to each other. It is very easy to set up 2 clients talking to each other. You will build your project for one client and run the chat within unity for the other.

To build your project go to File -> Build Settings… and select PC, Mac and Linux Standalone. Then click Build and Run.

Press Play in your Unity Editor. The Network Manager will show the default HUD. Click Lan Host.Once the project is built and is running, click LAN Client.

You can now chat between the two clients!

Conclusion

We have seen how we can write an online chat using Unity HLAPI. We represent one message in the chat with a Networked Game Object.

Further implementations could involve writing the chat without the help of the HLAPI; write a host server which accepts connections and acts as the middleman in exchanging messages between clients.

You can find the code for this chat on my personal GitHub: https://github.com/lormori/UnityChat

References

https://docs.unity3d.com/Manual/UNetUsingHLAPI.html