PUN Classic (v1), PUN 2 and Bolt are in maintenance mode. PUN 2 will support Unity 2019 to 2022, but no new features will be added. Of course all your PUN & Bolt projects will continue to work and run with the known performance in the future. For any upcoming or new projects: please switch to Photon Fusion or Quantum.
bolt | current

Simple Server-Controlled Chat

There are times when you even want your in-game chat to be controlled by the server, for example to either restrict the use of bad words, prevent spamming, or both.


On the player, attach a PlayerChatController which deals with input from the player and sends it to the server. We are using DF-GUI* for our GUI, hence the reference to dfTextbox, but the principles are the same regardless of which GUI-system you use;

* DF-GUI is no longer maintained, so please don't take this as a recommendation to use that GUI solution.

public class PlayerChatController : Bolt.EntityEventListener<IPlayerState> {

    dfTextbox chatInputTextbox;

    void Start () {
        chatInputTextbox = PlayerUI.instance.chatInputTextbox; // PlayerUI is a local, non-networked, singleton

    void Update () {
        // The chat input box is triggered when the player presses "T"
        if ( Input.GetKey(KeyCode.T) && !chatInputTextbox.IsVisible ) {
            chatInputTextbox.MaxLength = 140; // Bolt allows strings of max 140 chars length
            chatInputTextbox.Text = "";
            chatInputTextbox.IsVisible = true;

        // Things that can only happen if the chat input textbox is visible
        if ( chatInputTextbox.IsVisible ) {
            // Send message when player presses Enter/Return
            if ( Input.GetKeyDown(KeyCode.Return) ) {
                chatInputTextbox.IsVisible = false;
                chatInputTextbox.Trim(); // Removes spaces at the beginning and end; we don't want strings filled with spaces to bother us

                // Send the chat message to the server only for "quality check"
                if ( chatInputTextbox.Text.Length > 0 ) {
                    using ( var evnt = SendChatMsgToServer.Create(Bolt.GlobalTargets.OnlyServer) ) {
                        evnt.Sender = entity;
                        evnt.Message = chatInputTextbox.Text;

            // Abort (i.e. if pressing the ESC key)
            if ( Input.GetKeyDown(KeyCode.Escape) ) {
                chatInputTextbox.IsVisible = false;



This controller is attached to the player's user interface and takes care of displaying the chat messages, scrolling them, removing the oldest ones etc. It also handles the chat-events;

public class UI_ChatOutputController : Bolt.GlobalEventListener {

    public override void OnEvent ( SendChatMsgToServer evnt  ) {
         bool okToSend = true;

        // This is the place where you do all the checks to see if it's OK to forward the message to all the clients.
        // Then, if it's OK...

        if ( okToSend ) {
            // Send the message to everyone, including the server
            using ( var clientEvnt = SendChatMsgToClients(Bolt.GlobalTargets.Everyone) ) {
                clientEvnt.Message = evnt.Message;

    public override void OnEvent ( SendChatMsgToClients evnt ) {
        // This is where you receive the chat message from the server, adds it to your chat messages list/array and refreshes your GUI.


Two events for the same task?

You might notice that there are two events doing basically the same thing here; just sending a chat message around. You are free to use only one event, where the clients sends the event only to the server (as in the code above) and then the same event to send to all the clients (or to everyone, including the server, as in the code above.)

It's all up to you.

To Document Top