Reason behind SendMonoMessage?

ubhkid
ubhkid
Was doing an optimization pass on a scene we're preparing for our game when I discovered that SendMonoMessage() was allocating 7.1mb of memory each time it was called. I do realize the reason for the poor performance is due to the sheer scale of the scene that we're dealing with (20,000~ LOD objects). Still, why not target PhotonView game objects + MonoBehaviours that must be manually registered with Photon in order to receive MonoMessages?

Or maybe I'm completely missing something here...?

Comments

  • Ow, it allocates 7+MB every time? Even if it's calling methods that are already known?
    That might be related to the un-cached use of FindObjectsOfType.
    Actually, that is slow to begin with.

    The idea of registering the GOs that get updates is definitely interesting. At least, if those objects would register automatically for updates (through a component or so).
    I am not so sure how fast I can implement something that's useful for you. I have to make sure it doesn't break stuff and release and such...

    But I think you could modify the code accordingly in SendMonoMessage. Add a Dictionary of GOs that want callbacks and make them register (by adding themselves to it). As fallback (if the Dictionary is empty), find the GOs as done now.


    Anyways. Good point. Thanks for the heads up!
  • Oh we're alright now, I actually just took out the HashSet and List<MonoBehaviour> and replaced them with our own manager that registers MonoBehaviours that I specifically allow. It seems to be a nice solution while remaining very fast. It only took about 5 minutes to do:
    PhotonNetworkManager.MonoMessageGOs.Clear();
    for (int index = 0; index &lt; PhotonNetworkManager.MonoMessageList.Count; index++)
    {
        if (!PhotonNetworkManager.MonoMessageGOs.Contains(PhotonNetworkManager.MonoMessageList&#91;index&#93;.gameObject))
        {
            PhotonNetworkManager.MonoMessageGOs.Add(PhotonNetworkManager.MonoMessageList&#91;index&#93;.gameObject);
            if (parameters != null && parameters.Length == 1)
            {
                PhotonNetworkManager.MonoMessageList&#91;index&#93;.SendMessage(methodString.ToString(), parameters&#91;0&#93;, SendMessageOptions.DontRequireReceiver);
            }
            else
            {
                PhotonNetworkManager.MonoMessageList&#91;index&#93;.SendMessage(methodString.ToString(), parameters, SendMessageOptions.DontRequireReceiver);
            }
        }
    }
    

    Then to register we've just got:
    public static HashSet&lt;GameObject&gt; MonoMessageGOs = new HashSet&lt;GameObject&gt;();
    public static List&lt;MonoBehaviour&gt; MonoMessageList = new List&lt;MonoBehaviour&gt;();
    public static void RegisterPhotonMonoMessageReceiver(MonoBehaviour monoBehaviour)
    {
        MonoMessageList.Add(monoBehaviour);
    }
    
    public static void UnregisterPhotonMonoMessageReceiver(MonoBehaviour monoBehaviour)
    {
        MonoMessageList.Remove(monoBehaviour);
    }
    

    Seems to work well for us! :)

    *Edit: Just saw that you suggested doing almost exactly what I posted :P
  • That solution looks really clever.
    Does it matter that you only call SendMessage only once per GO?
  • Nope, this fits the bill perfectly for us. Down the line we may have photon view's also register with the manager, but for now we only have two GO's that really needed MonoMessages so the performance gains were very large!
  • I added a similar feature to the upcoming PUN version v1.23.
    This way, you won't have to keep your updates and it's easier for others to get the same improvement.
    Should be out next week.