Right way to call monobehaviour from photon listener

Options
gtidhar
edited June 2012 in DotNet
Hi guys,

We have a working photon-server solution for sometime now.

I seem to be having issues due to the calling of monobehaviour classes from delegates fired from the photon listener (mainly in the implementation of "PeerStatusCallback()" and "OperationResult()").

Currently, the delegates are set with methods coming from a monobehaviour class. It there any other way I should be doing the reference between unity and photon?

(For instance, I get this unity error:
"comparebaseobjects can only be called from the main thread." due to this call:
if (prefabGameObject == null )... // prefabGameObject is a prefab reference..)
which is done within the delegate method implementing the callback in the photon listener).

Comments

  • dreamora
    Options
    You are not using PUN (Photon Unity Networking from the Unity Asset store) or at least its public API but the .NET sdk, is that possible?
    Cause PUN does not offload callbacks and message handling to a different thread as far as I saw, nor does the regular Unity SDK. Only the normal .NET one does it cause .Net, unlike unity, is thread safe.

    You can not call into anything that extends from UnityEngine.object from a different thread.
    Prior to Unity 3.5.2 it simply crashed the engine commonly. Since Unity 3.5.2 you now get much more errors and warnings already in the editor upon compilation and testing.
  • gtidhar
    Options
    I am not using PUN.

    I am using PhotonUnity3D.dll.
  • dreamora
    Options
    If you don't use PUN this is the wrong board, the .net one would be the right. this one here is explicitely for PUN only.

    Anyway back on topic: Do you use the api the assembly offers or do you hook into underlying things?
    As far as I recall it should never call back from a different thread and I don't recall that I ever saw the situation you describe - unluckily since Photon 3 the library is no longer part of the server solution as it used to be in Photon 2 (where it was the .net library with a few additions) so I can't sure here, Kaiserludi will likely have to answer this one unless you want to use a .net reflector
  • Tobias
    Options
    Callbacks like PeerStatusCallback() are called from the same thread that your game uses to call DispatchIncomginCommands(). If you call that from Unity's main thread (in Update(), e.g.), then it should be the Main thread as well.

    If the problems remain, let me know. I'd like to get a callstack for those cases then.
  • gtidhar
    Options
    I created a different queue from photon's. so that photon fills it and unity reads it.
    I also moved the PhotonPeer.Service() to be called within a thread fired by ThreadPool instead of calling it from FixedUpdate(). I did that because in some cases, when the network is down, GetPolicySocket fails and being called by unity thread, makes the whole client get stuck. At least that what seemed to have caused this. Still testing the threaded solution.

    This stopped these errors from happening.
  • dreamora
    Options
    If the 'queue' is a static queue that you properly secure against multithreaded accesses then thats indeed a solution.

    If thats not what you did you will likely get phantom crashes you can not debug at all in case concurrent accesses happen as unity does not respect anything related to threading on its own code
  • Tobias
    Options
    > I created a different queue from photon's. so that photon fills it and unity reads it.
    Why that?
    You can pause calling DispatchIncomginCommands, if you keep on calling SendOutgoingCommands. This also queues everything and you don't have to do the same work that the lib does?
  • gtidhar
    Options
    Tobias wrote:
    > I created a different queue from photon's. so that photon fills it and unity reads it.
    Why that?
    You can pause calling DispatchIncomginCommands, if you keep on calling SendOutgoingCommands. This also queues everything and you don't have to do the same work that the lib does?

    Well, since calling unity functions from within the photon callbacks produces errors such as the one I've mentioned, I need a way to fetch the data received by photon from unity.
  • dreamora
    dreamora
    edited June 2012
    Options
    Don't do it through a ThraedPool but from Update or something even faster than that (coroutine started upon connecting which uses yield return new WaitForSeconds(0.016f) to get 60 network updates a second. or you 0.01 for 100 of them though thats too much for anything but the master client) and you have no longer the need for an intermediate threadsafe queue as it is the case with a Thread or the threadPool
  • Tobias
    Options
    gtidhar wrote:
    Well, since calling unity functions from within the photon callbacks produces errors such as the one I've mentioned, I need a way to fetch the data received by photon from unity.

    See post above: Everything is queued. If you call dispatch from the Update() method, you will be in the main thread of Unity and you can skip dispatch if you don't want incoming data for a while.

    Let me know how that does. An extra thread sounds like a waste of performance and introduces more complexity.