Can I mix PUN and Realtime?

Hi, I am new to Photon so please forgive the possibly dumb question.

Can I mix calls to the PUN and Realtime APIs in the same application? E.g., can I connect to the Photon Network with LoadBalancingClient.Connect (Realtime) and then use PhotonNetwork.CreateRoom (PUN)?

The context: I'd like to write a library based on Realtime, that could be used outside of Unity. Some of the apps using this library will be Unity apps though. So I'd like to know if those need to stick to the Realtime API or can access Photon through the PUN API as well.

Best Answers

Answers

  • JohnTube
    JohnTube ✭✭✭✭✭
    Hi @fiban,

    Thank you for choosing Photon!

    If by mix you mean that one client made of Photon Realtime SDK can communicate with another client made of PUN, then the answer is YES.
    You need to consider a few things, however:
    mainly AppVersion
    in general "Matchmaking Checklist".
  • Thanks JohnTube.

    I actually meant using both PUN and Realtime in the same client/process. See my example about using both LoadThe Realtime binding is available in the PUN package so in theory this seems possible,
  • JohnTube
    JohnTube ✭✭✭✭✭
    You can also use both from the same process, yes but you will have two Photon clients, two connections and twice the CCU. For what purpose is this?
  • @JohnTube:
    I think what he has in mind is that he mixes API calls on the same connection like in doing the connect() call directly on the LoadBalancingClient, but then calling PUNs createRoom() on that very connection. This would require being able to directly access the LoadBalancing Client instance that is used by PUN under the hood.

    @fiban:
    AFAIK PUN exposes its LoadBalancingClient instance, so you could access it and do just that, but a mixed use like that would result in undefined behavior and most likely break things, because LoadBalancingClient::someFunction() would not do any additional work that the same function in PUN might do like changes to PUNs states.
  • JohnTube
    JohnTube ✭✭✭✭✭
    @Kaiserludi
    Ah OK I see now.
    It's possible yes.
    You need to use either PhotonNetwork methods or PhotonNetwork.NetworkingClient.
    But why do you need that? PhotonNetwork wraps most if not all of the LoadBalancingClient's methods.
    Assuming you use PUN2 of course.
  • What I'd like to do goes the other way around actually. I'd like to setup a connection using Realtime then use PUN features on top of it.

    I'd like to write a library that provides networking functionality (establishing a connection, sending data) by wrapping Photon and can be used outside of Unity - because of this, I figure it should use Realtime (LoadBalancingClient) internally. Then, if this library is used in a Unity application, it would be nice if the app could use higher level features of PUN (e.g. PhotonView) on top of the connection established by my library.

    @JohnTube thanks for pointing out NetworkingClient. It's a public mutable field, so maybe I can just replace it with the LoadBalancingClient used by my library? (sounds very hacky so I don't have my hopes high). Alternatively I could write my library so that it can accept an existing LoadBalancingClient rather than creating a new one, and I can pass PhotonNetwork.NetworkingClient to it at startup.

    As @Kaiserludi points out though, even if I make sure that both PhotonNetwork and my library use the same LoadBalancingClient, then mixed API use might corrupt some PUN state. Are there any guarantees/guidelines in regard to calling functions on PhotonNetwork.NetworkingClient directly *and* indirectly through the other PUN functions/classes?
  • JohnTube
    JohnTube ✭✭✭✭✭
    Hi @fiban,

    I still don't get why do you need this?

    What does your own custom LoadBalancingClient add?
    What does your networking library add?

    We have Photon Realtime for .Net that can be used outside of Unity and it's the same as the one we use in Unity from features and behaviour perspectives.

    Why can't you use what we provide already as callbacks or events in PUN or PhotonNetwork.NetworkingClient?
  • @JohnTube:
    This is what I understand he wants to do:
    - Write a library that is built on top of our .NET Realtime Client SDK
    - use this library from within non-unity and unity-apps (hence he can't use PUN, to not restrict it to only Unity apps)
    - make it possible for the Unity apps to use PUN features likes PhotonViews, RPCs, etc. on the connection that has been established by his Realtime Client wrapper lib
  • @Kaiserludi yes you got that perfectly.
  • JohnTube
    JohnTube ✭✭✭✭✭
    It's possible but it's reinventing the wheel.
    So this is like making your own client that works with our servers and re-implementing PUN features in it.
    If you're fine with it, feel free to do so, source code is provided for Realtime and PUN.
  • @JohnTube I might not have been perfectly clear. I don't plan to re-implement PUN features, or Realtime features for that matter.

    - I am writing a library that provides networking features based on the Photon network. I want this library to be used outside of Unity, so it's going to use the Realtime SDK and not PUN. This library is not a PUN emulation but has domain-specific logic that is not implemented by neither PUN nor Realtime (e.g. specific logic for room management or messaging).
    - At runtime, this library is going to instantiate/use internally a LoadBalancingClient through the Realtime API.
    - Apps will generally go through the library API to use networking features, but the library might also expose the LoadBalancingClient for direct access.
    - This library might be included in Unity apps. Unity apps will have access to the library API (and possibly to the LoadBalancingClient and Realtime API) as all other apps. *In addition* I would like for Unity apps to be able to, somehow, use PUN features (PhotonViews, RPC, etc) on top of the connection/LoadBalancingClient established by my library.

    Now, my question is whether a flow like:
    1. call PhotonNetwork.Connect*()
    2. pass PhotonNetwork.NetworkingClient to my library
    3. call lbc.OpJoinRoom(...) and/or other Realtime API in my library
    4. use a PhotonView/RPC and/or other PUN features in the Unity app
    will work as expected at runtime or will produce inconsistencies in the PUN state - in general, to what amount it is possible to mix calls to PUN and Realtime API acting on the same LoadBalancingClient. Since PhotonNetwork.NetworkingClient is public I would expect that some mixing is possible, OTOH I would like some guarantee that it doesn't corrupt the PhotonNetwork state.
  • JohnTube
    JohnTube ✭✭✭✭✭
    has domain-specific logic that is not implemented by neither PUN nor Realtime (e.g. specific logic for room management or messaging)
    I still can't see why you can't use PUN or Realtime for this.
  • I thought you wanted the other way around: inject your own custom LoadBalancingClient (or subclass) into PUN.

    That would be even better! But if anyone tells me that doesn't work, I can go with injecting PhotonNetwork.NetworkingClient in my library.

    Could you specify "other Realtime API"?

    Right now, I don't know the exact extent of the API I will need; I'd say room management methods, event raising and room/player properties at least. I understand that it might be case-by-case, but it's good to know that there are things that will surely work (events, properties) and that will surely not work (offline mode).

    I don't see a benefit from calling this outside of PUN

    As written above, my library needs to be Unity-agnostic so the code in it cannot use PUN, it can only use Realtime.

    has domain-specific logic that is not implemented by neither PUN nor Realtime (e.g. specific logic for room management or messaging)

    I still can't see why you can't use PUN or Realtime for this.

    Because it is domain-specific logic that is not implemented by neither PUN nor Realtime :smile: I am talking about my writing my game-related logic *on top* of Realtime/PUN here, not reimplementing what is already in Realtime/PUN.
  • JohnTube
    JohnTube ✭✭✭✭✭
    I'm assuming you use PUN2.
    The same Photon Realtime (code available under "Photon/PhotonRealtime" + lib) is available outside of Unity! Did you try it? Did you download and open the .Net SDK?
    If you want to add code on top of Realtime then why not use Realtime as is?
  • Thanks @Tobias, that more or less answers my question. I understand that what I am trying to do is hacky :smile: Just want to figure out within what boundaries I can operate.

    If I have understood correctly, raising events on the LBC and setting properties (plus any operation on Rooms and Players I guess, since PUN and Realtime share the same classes) should work fine. Working in offline mode or mixing connection/matchmaking-related calls will probably not.

    If you can think to any other combination that most surely works or doesn't, feel free to add!
  • Good point, thanks!
  • Kaiserludi
    Kaiserludi admin
    edited May 2019
    Hi @fiban.
    If I were in your situation, then I would go with the following approach:
    - Initialize your lib with a constructor or init-function that has two overloads: One that takes a LoadBalancingClient instance and assigns it to a member variable of type LoadBalancingClient and one that takes a NetworkingPeer instance and assigns it to a different member variable of type NetworkingPeer. The second one could be in Unity #ifdefs.
    
    #ifdef UNITY
    void init(NetworkingPeer peer)
    {
        networkingPeer = peer;
    }
    #endif
    void init(LoadBalancingClient client)
    {
        loadBalancingClient = client;
    }
    
    - Let all your code that operates on the passed-in client instance check if your NetworkingPeer member variable is non-null and if that check evaluates to true, then operate on that member, otherwise operate on the LoadBalancingClient member. Of course the whole if-block + the else keyword could be inside Unity #ifdefs to avoid unnecessary overhead for non-Unity clients.
    Of course you should be able to abstract this away behind a photonlayer-agnostic interface, which can be called by other parts of your code
    Example:
    
    void sendData(Object data)
    {
    #ifdef UNITY
        if(networkingPeer)
            networkingPeer.OpRaiseEvent(data);
        else
    #endif
            loadBalancingClient.OpRaiseEvent(data);
    }
    
    This way in the future you potentially could add more supported underlying implementations additionally to the two initially supported ones, without the need to touch the rest of your code that can continue to just call the platform-agnostic interface.
  • @Kaiserludi I don't think I need two different overloads, since PhotonNetwork.NetworkingClient (the property) is in fact an instance of LoadBalancingClient. So I should be fine taking a LoadBalancingClient in my initialization.
  • Hi @fiban.

    Sorry, I actually meant a NetworkingPeer. I have fixed it in my previous post.
  • @Kaiserludi from what I understand that's what PhotonNetwork in PUNv1 uses in place of LoadBalancingClient, right?

    At the moment I am mostly looking at PUN2, but yeah, if the need for supporting PUN1 apps arises, yours looks like a good solution.