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.


There are two types of events in Bolt. Global events and entity events. Global events are sent at a connection level and not to a particular entity. Global events have a number of overrides that allow them to fine tune who receives the event (either defined in the Bolt event in the user interface or overridden through code). Entity events are sent to a BoltEntity.

Event Types

Global Events:

Global events can be either be ReliableOrdered or Unreliable. In order to create an event you first must have defined it in Bolt and then you must compile Bolt (in order to generate the backing code for the new event as Bolt uses a code generator behind the scenes).

Entity Events:

Entity events are always unreliable. They are sent to an explicit Bolt entity and Bolt will automatically ignore connections that do not have the entity scoped to it when sending entity events.

Back To Top

Events Reliability

Reliable Events:

Reliable events in Bolt are guaranteed to arrive and to arrive in the order they were sent. The only reliable events that can be sent in Bolt are Global Events.

There is a 3 byte overhead per reliable event.

Unreliable Events:

Remember that Bolt does not send events as a separate packet. The way Bolt works is that it packs everything (state, events, etc) into a single packet each send tick based on your SendRate (see Packets Under the Hood, above). For unreliable events, Bolt will try to pack the event into this packet in two subsequent send ticks; if it was unable to fit the event in either of those attempts, it will drop the event. Essentially Bolt will try to fit unreliable events into the end of the packet if any space is remaining. It will try in two subsequent packets to fit the event into the packet and after that it just gives up and deletes the event. Keep in mind “unreliable” in this context has nothing to do with an “unreliable” network packet in the traditional sense.

There is a 1 byte overhead per unreliable event.

Back To Top


Also note that Bolt will not buffer events. If an event arrives for an entity (via an entity event) and the entity doesn’t exist, Bolt will just drop the event. If you need a reliable entity event you should just use a global event with the entity as a field of the event. However, keep in mind that since Bolt packs events and states together in a single packet, not everything can make it into a packet for each send tick - this means that if you try to send an event to an entity right after creating it, you will find that sometimes the event arrives before or after the entity is created. Bolt events and entities are created in separate logical streams in the packet and they will not be ordered with respect to each other.

Back To Top

Bolt Event Generation

Bolt will generate a new class for your event derived from the Bolt Event class after you compile Bolt. So if we created an event EventTest then Bolt would generate (you can see this event metadata by right clicking on it in Visual Studio and clicking Go To Definition):

public class EventTest : Event
    // ...

You then can create the event with one of the the static creation methods. Each of these methods allows you to specify endpoint information. If you specify no target information the defaults from the Event specified in Bolt will be used. If you just want to send the event to a particular connection there is an override specifically for that.

public static EventTest Create();
public static EventTest Create(BoltConnection connection);
public static EventTest Create(GlobalTargets targets);
public static EventTest Create(BoltEntity entity);
public static EventTest Create(ReliabilityModes reliability);
public static EventTest Create(BoltEntity entity,EntityTargets targets);
public static EventTest Create(GlobalTargets targets,ReliabilityModes reliability);
public static EventTest Create(BoltConnection connection,ReliabilityModes reliability);

Once you create your event you can populate the event with your data. The Bolt code generator will generate fields for all of the data you added when you created the event in Bolt and compiled Bolt. For example, if we had added a field called “MyField” as an integer in Bolt for this event we could do:

// Create and setup
var myEvent = EventTest.Create(GlobalTargets.AllClients);
myEvent.MyField = 5;

// Send the event

Back To Top

Receiving Global Events

You can receive global events by deriving a class from GlobalEventListener and adding it to the scene. Bolt will automatically find all GlobalEventListeners and register them if they are in the scene when Bolt starts. However, Bolt will de-register them after it shuts down so if you are using a singleton listener and you want the listeners to persist make sure that you override PersistBetweenStartupAndShutdown in your derived class and return true.

You can also decorate a GlobalEventListener derived class with [BoltGlobalBehaviour()], and using the various parameters have that listener automatically created when Bolt starts (the two common scenarios using this attribute are adding network type specific listeners (i.e. client vs server) or scene specific listeners). This is used in the tutorials.

Once you have a GlobalEventListener derived class you can simply override the event handler for the global event you are interested in and implement your logic for receiving the event.

You can also register your own listeners with BoltNetwork.AddGlobalEventListener and BoltNetwork.RemoveGlobalEventListener. You can also register for singular events with BoltNetwork.AddGlobalEventCallback and BoltNetwork.RemoveGlobalEventCallback although I have not used them myself. You could also forgot GlobalEventListener and implement the interfaces yourself and manually register the listeners.

You can retrieve the connection that sent the event with EventInstance.RaisedBy.

Back To Top


This interface can be implemented on Bolt.GlobalEventListener, Bolt.EntityEventListener and Bolt.EntityEventListener<T> in order to modify if the event is still raised if the MonoBehaviour/GameObject is disabled (by default it will not be raised).

public interface IEventListener
    bool InvokeIfDisabled { get; }
    bool InvokeIfGameObjectIsInactive { get; }


public class BoltServerCallbacks : Bolt.GlobalEventListener, Bolt.IEventListener
    public bool InvokeIfDisabled { return true; }
    public bool InvokeIfGameObjectIsInactive { return true; }
    // event callback overrides below

To Document Top