FPS Drop while using SetCustomProperties

Options
Hello. While working with Photon Cloud I started actively using built-in hashtables (player props) for syncing data between players. And I noticed a significant FPS drop after that. Here I provide a solution for this issue.

Issue:
When frequently using PhotonNetwork.player.SetCustomProperties (a call to SetCustomProperties) or PhotonNetwork.room.SetCustomProperties methods a big fps drop happens. Up to a full stop of the execution of the application. The same issue happens when another player changes his props or room props - and the data is being synced to your client. (readoutStandardProperties or ReadoutProperties in NetworkingPeer.cs, depending on PUN version).

The cause of the issue:
In all these cases SetCustomProperties calls SendMonoMessage (NetworkingPeer.cs). The following things happen: all gameobjects on the scene with MonoBehaviours are being found, after that SendMessage is being called on them (OnPhotonPlayerPropertiesChanged or OnPhotonCustomRoomPropertiesChanged).
public static void SendMonoMessage(PhotonNetworkingMessage methodString, params object[] parameters)
{
HashSet<GameObject> haveSendGOS = new HashSet<GameObject>();
MonoBehaviour[] mos = (MonoBehaviour[])GameObject.FindObjectsOfType(typeof(MonoBehaviour));
for (int index = 0; index < mos.Length; index++)
{
MonoBehaviour mo = mos[index];
if (!haveSendGOS.Contains(mo.gameObject))
{
haveSendGOS.Add(mo.gameObject);
if (parameters != null && parameters.Length == 1)
{
mo.SendMessage(methodString.ToString(), parameters[0], SendMessageOptions.DontRequireReceiver);
}
else
{
mo.SendMessage(methodString.ToString(), parameters, SendMessageOptions.DontRequireReceiver);
}
}
}
}

So if lot's of gameobjects with monobehaviours are present in scene - the game super lags because of SendMessage's bad performance.

Solution:
Create a variable in PhotonNetwork.cs where you set up the object which need to receive photon events. And then in SendMonoMessage() we access this preinitialized variable and send SendMessage only to them. My implementation:
1. public static GameObject eventsListener; added to PhotonNetwork.cs

2. SendMonoMessage method in NetworkPeer.cs changed to the following one:
public static void SendMonoMessage(PhotonNetworkingMessage methodString, params object[] parameters)
{
if (parameters != null && parameters.Length == 1)
{
PhotonNetwork.eventsListener.SendMessage(methodString.ToString(), parameters[0], SendMessageOptions.DontRequireReceiver);
}
else
{
PhotonNetwork.eventsListener.SendMessage(methodString.ToString(), parameters, SendMessageOptions.DontRequireReceiver);
}
}

Notes:
Yes, this way we modify PUN code, and we need to do this when updating the PUN version. I hope a built-in implementation of this can be added to PUN by exitgames.
SendMonoMessage - is the method that broadcasts absolutely all messages (OnCreateRoom OnJoinedRoom and so on)

P.S. there may be other issues with SendMonoMessage in PUN, I didn't investigate.

Could you fix this?

thanks,
Slav

Comments

  • Tobias
    Options
    Hm, you make a good point.
    I do realize that SendMonoMessage is a real performance problem still. However, everyone is used to callbacks on ANY script all the time. That's how Unity does it, so I didn't want to change it.
    Maybe your solution could be an alternative. If the listener is defined, I'm only using that.
    Alternatively I could at least skip the "Find(MonoBehaviour)" call if we limit the calls to the game objects that have PhotonViews.

    I will consider it for one of the upcoming PUN versions but I will try to keep the current implementation, too.