RPCs and RaiseEvent

One feature that sets PUN aside from other Photon packages is the support for Remote Procedure Calls (RPCs).

Remote Procedure Calls

Remote Procedure Calls are exactly what the name implies: Method-calls on remote clients (in the same room).

To enable remote calling for some method, you must apply the attribute: [PunRPC].

void ChatMessage(string a, string b)
    Debug.Log(string.Format("ChatMessage {0} {1}", a, b));
Unity 5.1 made the RPC attribute obsolete and it will be removed later on. Due to that, PUN uses another attribute: PunRPC, beginning in v1.56. All other usages of RPC and "Remote Procedure Call" are unaffected.

To call the functions marked as RPC, you need a PhotonView. Example call:

PhotonView photonView = PhotonView.Get(this);
photonView.RPC("ChatMessage", PhotonTargets.All, "jup", "and jup!");

Pro tip: If your script is a Photon.MonoBehaviour or Photon.PunBehaviour you can use: this.photonView.RPC().

So, instead of directly calling the target method, call RPC() on a PhotonView and provide the name of the method to call.

Targets and Parameters

The PhotonView is like a "target" for the RPC: All clients execute the method only on the networked GameObject with that specific PhotonView. If you hit a specific object and call "ApplyDamage" RPC, then the receiving clients will apply the damage to the same object!

You can add multiple parameters (provided PUN can serialize them). When you do, the method and the call must have the same parameters. If the receiving client can’t find a matching method, it will log an error.

There is one exception to this rule: The last parameter of a RPC method can be of type PhotonMessageInfo, which will provide the context for each call. You don't set the PhotonMessageInfo in the call.

void ChatMessage(string a, string b, PhotonMessageInfo info)
    // the photonView.RPC() call is the same as without the info parameter.
    // the info.sender is the player who called the RPC.
    Debug.Log(string.Format("Info: {0} {1} {2}", info.sender, info.photonView, info.timestamp));

With the sender being in the PhotonMessageInfo and the "targetting" via PhotonView, you can implement shooting someone without extra parameters. You know who shot and what was hit.

Targets, Buffering and Order

You can define which clients execute an RPC. To do that, use the values of PhotonTargets. Most commonly, you want All clients to call the RPC. Sometimes only Others.

PhotonTargets has some values ending on Buffered. The server will remember those RPCs and when a new player joins, it gets the RPC, even though it happened earlier. Use this with care, as the a long buffer causes longer join times.

PhotonTargets has values ending on ViaServer. Usually, when the sending client has to execute an RPC, it does so immediately - without sending the RPC through the server. This, however, affects the order of events, because there is no lag when you call a method locally.

ViaServer disables the "All" shortcut. This is especially interesting when RPCs should be done in order: RPCs sent through the server are executed in the same order by all receiving clients. It is the order of arrival on the server.

Example: In a racing game you could send the RPC "finished" as AllViaServer. The first "finished" RPC call will tell you who won. The following "finished" calls will tell you who's on the ranks.

Shortcuts for RPC Names

Because strings are not the most effective piece to send via network, PUN uses a trick to cut them short. PUN detects RPCs in the Editor and compiles a list. Each method name gets an ID via that list and when you call an RPC by name, PUN will silently just send the ID.

Due to this shortcut, different builds of games maybe don't use the same IDs for RPCs. If this is a problem, you can disable the shortcut. However, if clients of the same build are matched, this is not a problem.

The list of RPCs is stored and managed via the PhotonServerSettings.

If RPC calls go wrong between different builds of a project, check this list. The Get HashCode button calculates a hashcode, which is easy to compare between project folders.

If required, you can clear the list (Clear RPCs button) and refresh the list manually by clicking Refresh RPC List button.


In some cases, RPCs are not exactly what you need. They need a PhotonView and some method to be called.

With PhotonNetwork.RaiseEvent, you can make up your own events and send them without relation to some networked object. Make up a code and some content and send it:

byte evCode = 0;    // my event 0. could be used as "group units"
byte[] content = new byte[] { 1, 2, 5, 10 };    // e.g. selected unity 1,2,5 and 10
bool reliable = true;
PhotonNetwork.RaiseEvent(evCode, content, reliable, null);

The content can be anything that PUN can serialize. You can use an object[] and mix selected units with their destination, e.g..

To receive the event, a script needs to implement an EventCallback and register it. PUN does not use a general callback for performance reasons. Implement this in a MonoBehaviour to handle events:

// setup our OnEvent as callback:
void OnEnable()
    PhotonNetwork.OnEventCall += this.OnEvent;
void OnDisable()
    PhotonNetwork.OnEventCall -= this.OnEvent;
// handle custom events:
void OnEvent(byte eventcode, object content, int senderid)
    if (eventcode == 0)
        PhotonPlayer sender = PhotonPlayer.Find(senderid);  // who sent this?
        byte[] selected = content as byte[];
        for(int i=0; i < selected.Length; i++)
            byte unitId = selected[i];
            // do something

The example code is not very useful, but you get the idea. You can make up event codes and use each in a different way with different content.

Under the hood, PUN also uses RaiseEvent for pretty much all communication.

Raise Event Options

With the RaiseEventOptions parameter, you define which clients get the event, if it's buffered and more.

Receiver Groups

"Receiver Groups" are an alternative way to define who receives an event. This option is available via RaiseEventOptions.

There are three defined groups:

  • "Others": all other active actors joined to the same room.
  • "All": all active actors joined to the same room including sender.
  • "MasterClient": currently designated Master Client inside the room.

Caching Options

The most interesting option is probably the event cache / buffering. PUN uses that for Instantiate and it can be useful when new (joining) players should get events that happened even before they were in the room.

RaiseEventOptions.EventCaching has three important options: AddToRoomCache, AddToRoomCacheGlobal and RemoveFromRoomCache. These work best when you send a Hashtable in an event.

Calling RaiseEvent with EventCaching.AddToRoomCache, the event will be put into the server's cache. That means, any player who joins later on, will also get the event. New players get cached events in the order they arrived on the server.

When a player leaves, the cached events get automatically removed from the cache. To avoid this for specific events, call RaiseEvent with EventCaching.AddToRoomCacheGlobal. That puts the event into the "room's event cache".

If you put a lot of events into the cache, new players will get a lot of messages when they get into the room. This can take a moment for larger numbers of events, so you should clean up stuff that's no longer relevant, which is done with EventCaching.RemoveFromRoomCache.

When you use RemoveFromRoomCache, the EventCode of RaiseEvent will be used as filter. So instead of setting some event, you can remove all instances of it.

To get more fine control, the content of an event can be used for filtering. For that, you have to use a Hashtable as content type. You can set a key/value pair to identify a specific event and when you RaiseEvent with RemoveFromRoomCache, you only have that key/value pair in the content filter.

You can identify individual events this way, or events belonging to some object or turn or whatever.

Read more about events cache here.

 To Document Top