Some coding / architecture questions for PUN, for a game like Clash royale.

Hi,

First time using Photon for a project so I have a few questions.

1. How do I avoid using buffered calls to the game? The game has a feature that you have to draw out your territory using a hexagon grid. So I have to somehow sync this so that the other player will always get the info, even if they disconnect and reconnect a bit later. Should I be trying something like Room CustomProperties for this? I have tried some other thing like automaticallySyncScene = true but it didnt do anything.. (I didnt use PhotonNetwork.LoadLevel because the whole game's just one scene atm).

2. What should I use to store the data of the players profiles and the levels of their cards, etc? I've saw some platforms before like GameSparks, not sure if its the right solution.

Cheers

Comments

  • Also should I be using Photon PUN for this, or other solutions?
  • Hi @AceAzure,

    How do I avoid using buffered calls to the game?


    Simply don't use them. :D As far as I see you don't have to use buffered call anyway.

    Should I be trying something like Room CustomProperties for this?


    The Custom Room Properties are one way to achieve what you want to have. Another one is to use a custom Grid- / MapManager (or whatever you like to call it), which is present on both clients. In this approach the clients can use the RaiseEvent function in order to send custom events. The manager then can receive those custom events and deal with them, for example by coloring a certain tile on the map.

    [...] even if they disconnect and reconnect a bit later.


    If you are using the Custom Room Properties for synchronization, a rejoining client will automatically get those properties and would update the map on his own. Rejoining the game however might take some time. This depends on the amount of data which is stored and gets transferred. If you use the other approach I suggested, the client who is still in the room, would have to update the rejoining client. Therefore you could use the void OnPhotonPlayerConnected(PhotonPlayer newPlayer) callback and send a custom event to this certain client.

    I have tried some other thing like automaticallySyncScene = true but it didnt do anything..


    This one just makes sure, that each client in the room loads the same scene, if the MasterClient had used PhotonNetwork.LoadLevel(...). It has nothing to do with synchronization inside a certain scene, you have to use other ways for it.

    2. What should I use to store the data of the players profiles and the levels of their cards, etc? I've saw some platforms before like GameSparks, not sure if its the right solution.


    You can basically use any other service that persists player data in a way you want to store them (as long as it supported by the service). You can for example also check out our partners at PlayFab. For this service we already provide a documentation page about how to integrate the service in your game.

    Also should I be using Photon PUN for this, or other solutions?


    PUN is a good solution for this scenario.
  • It doesn't sound wise in a 2-player match to have 1 player disconnect during it, as you seemed to imply. That would mean that just 1 client is holding the entire gamestate.

    Just an interesting tidbit for you: Clash Royale has an intentional 1-second delay built into all actions, to avoid lag.
  • @Christian_Simon Thanks! appreciate all the great answers, I'll look into it.

    I've tried using Room.CustomProperties for the setting of grid squares and it worked.

    So basically from what I understand, RaiseEvent is a more advanced version of a RPC call. And CacheOption.AddToRoomCache is something like a buffered call... except you can control and use the information that's being passed on a rejoin?

    This is sorta what I have so far:

    Now the question is, how can i make it so that the buildings are also synced on both scenes, no matter disconnection? I'm guessing its the same logic and I make an enum for the building type and pass it in the RaiseEvent or room properties.
  • Joehot200 said:

    It doesn't sound wise in a 2-player match to have 1 player disconnect during it, as you seemed to imply. That would mean that just 1 client is holding the entire gamestate.

    Just an interesting tidbit for you: Clash Royale has an intentional 1-second delay built into all actions, to avoid lag.

    Thanks for the info about clash. You know in Clash royale how you can disconnect for a while and come back, and the game is still running? The game goes on for 3 minutes lets say, you can theoretically disconnect for the majority of the game and still come back to play if your king tower isn't destroyed.
  • https://hastebin.com/muwijebequ.cpp

    is this correct? Seems to be working okay
  • Joehot200
    Joehot200
    edited July 2018
    AceAzure said:

    Joehot200 said:

    It doesn't sound wise in a 2-player match to have 1 player disconnect during it, as you seemed to imply. That would mean that just 1 client is holding the entire gamestate.

    Just an interesting tidbit for you: Clash Royale has an intentional 1-second delay built into all actions, to avoid lag.

    Thanks for the info about clash. You know in Clash royale how you can disconnect for a while and come back, and the game is still running? The game goes on for 3 minutes lets say, you can theoretically disconnect for the majority of the game and still come back to play if your king tower isn't destroyed.
    The problem that you will always encounter with PUN is the lack of a server that can execute game logic.

    It's true that you can save a lot of your state to custom properties or cached events (to be honest, I know little about this, as it is not required for my game), however the main problem you will always face is that you then have only 1 client running the entire game, or 0 clients if that client disconnects.

    When using RaiseEvent, make sure to also use EventCaching.RemoveFromRoomCache to remove the event from the room cache when it isn't relevant. Otherwise, rejoining players will get flooded with unnecessary messages.

    By the way, I just read your post again and saw point number 2. I know somebody else suggested PlayFab, and I thoroughly agree with them. Not only can you login with device ID (or google play), but it also has an inventory system, and is also a partner of Exit Games, and has built-in integration with PUN,
  • @Joehot200

    Thanks for the advice. Why is it a problem with lack of server? I've been using IsMasterClient and it has been fine so far. I've made my player objects invisible and have everything as scene objects. Just the players are responsible for the input so they are like ghost objects and so they can come & go as they please.
  • Update: looks like the caching works to a degree, like everything is working great except the second time I connect, it keeps spawning more structures because of the cached items not getting removed. So in terms of code how can I remove the event from the cache after it's been used once from reconnecting players?
  • So in terms of code how can I remove the event from the cache after it's been used once from reconnecting players?


    You would have to remove the buffered message manually afterwards. To see how this works, you can take a look at the Cached Events documentation page.

    Now the question is, how can i make it so that the buildings are also synced on both scenes, no matter disconnection?


    In my opinion you shouldn't use RaiseEvent for those objects. Instead try to use PhotonNetwork.Instantiate for creating certain objects on all clients and either the PhotonTransformView or a custom OnPhotonSerializeView solution for synchronizing those objects. Please correct me if I misunderstood the question.

    So basically from what I understand, RaiseEvent is a more advanced version of a RPC call.


    Internally a RPC is just a special RaiseEvent call with predefined parameters.
  • @Christian_Simon

    I read the Cached Events documentation but I didn't understand how to remove the cached event... it seems like you have to raise the event once again, just to remove it... seems counter intuitive.

    Also, I dont think PhotonNetwork.Instantiate works because I want to make it like Clash Royale in terms of how they handle their disconnects. As I said before I made everything in the scene be scene objects and the players are invisible, only responsible for the input ... so that when they leave or disconnect, nothing in the scene disappears (they will if instantiated with PhotonNetwork), right? Even if I told it not to cleanup player objects, then it behaved really funky and tried to instantiate again when player was connected.

    https://gfycat.com/LightheartedSatisfiedKookaburra

    In this gif, you can see what I tried to do. After building some structures on the editor in the right, I pressed the disconnect button on that game instance, then i made some buildings on the left game instance and let them shoot for a while, and then I reconnected to the instance on the right again and you see everything is updated as I want it.

    So this means that players can disconnect and comeback to a matched game state. Except there's a little problem right now I guess is that when you disconnect, the buildings no longer shoot and I guess I need to handle everything for shooting on the MasterClient.

    The code I have right now is http://hatebin.com/lundwwpsno , I'm resorting back to just using RPC calls and using Room CustomProperties for this instead of RaiseEvent. I guess the downside is that the hashtable for the storage can get very big and every time you reconnect, it will loop thru every one of them.
  • Even if I told it not to cleanup player objects, then it behaved really funky and tried to instantiate again when player was connected.


    I guess this is correct in this case, as the player who joins again receives all cached events, including those you are using for instantiation. In your case you don't remove the objects and therefore the client who rejoins instantiates all of the objects again. If you want to give this approach another try, you can try to use the OnLeftRoom callback for example, to remove the manually instantiated objects and let the client re-instantiate them when rejoining the room.

    Except there's a little problem right now I guess is that when you disconnect, the buildings no longer shoot and I guess I need to handle everything for shooting on the MasterClient.


    As far as I know those are Scene Objects right now, aren't they? In this case, the Ownership is automatically transferred to the (new) MasterClient in the room. I'm not sure why exactly the buildings don't shoot any longer (might be a game logic related problem) but usually the attached scripts are running as before.