Проблема:
При частом использовании методов PhotonNetwork.player.SetCustomProperties (любой вызов SetCustomProperties у player) или PhotonNetwork.room.SetCustomProperties происходит резкое падение фпс. Причем, может доходить до того, что приложение совсем встает. Это же явление наблюдается в тот момент, когда другой игрок изменяет свои параметры или параметры комнаты, а на вашей машине происходит синхронизация (методы readoutStandardProperties или ReadoutProperties в последней версии фотона в скрипте NetworkingPeer).
Причины:
Во всех этих случаях, внутри функций SetCustomProperties вызывается метод SendMonoMessage (скрипт NetworkingPeer). В этом методе происходит следующее: находятся все объекты на сцене у которых есть скрипты (любые MonoBehaviour), после чего на всех этих объектах вызывается SendMessage в который передается вызов соответствующего события (OnPhotonPlayerPropertiesChanged или OnPhotonCustomRoomPropertiesChanged в данном случае).
Синтаксис:
Используется csharp
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);
}
}
}
}
{
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);
}
}
}
}
Таким образом, если на сцене присутсвует большое количество объектов со скриптами, то данный метод тормозит работу всего приложения (из-за прожорливости SendMessage)
Решение:
Создание в PhotonNetwork переменной, в которой заранее задаются объекты, которым необходимо рассылать оповещения о фотоновский событиях. Это может быть что угодно (одиночный объект, массив, список, хэш). И далее в методе SendMonoMessage мы обращаемся к этой заранее проинициализированной переменной и отправляем события только на объекты указанные в ней. У меня это выглядит следующим образом:
1. в скрипт PhotonNetwork добавил public static GameObject eventsListener;
2. в скрипте NetworkPeer изменил метод SendMonoMessage на следующий:
Синтаксис:
Используется csharp
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);
}
}
{
if (parameters != null && parameters.Length == 1)
{
PhotonNetwork.eventsListener.SendMessage(methodString.ToString(), parameters[0], SendMessageOptions.DontRequireReceiver);
}
else
{
PhotonNetwork.eventsListener.SendMessage(methodString.ToString(), parameters, SendMessageOptions.DontRequireReceiver);
}
}
Премичания:
Да, таким образом вы правите скрипты фотона, и прийдется делать это каждый раз при его обновлении (Ну если, конечно, фотоновцы сами это не поправят)
SendMonoMessage - является методом, который рассылает абсолютно все сообщения (OnCreateRoom OnJoinedRoom и так далее)