Async Clarification
Sorry if this has been asked 1000 times, I could not find a question that answered how to do this exactly. I am currently trying to make a game where people play eachother over the phone asynchronously, meaning they can get on the game, do their turn, then get off the app and the game wont end when nobody is currently on the game. Photon offers a asynchronous method and webhooks/webrpc but I'm looking for a little clarification. According to Photon, the async method allows for RoomState to be autosaved by photon. I was wondering if this includes the game state (positions, health, characters in game). If not (which i think it does not), I believe the best way is to serialize all important Game data in a json gamestate string and save it somewhere (aws? azure? whats a good external web service, im a little confused on how i get an http address from an external web service). THen retrieve this string on the start of next turn or when somebody joins/rejoins? I was wondering if anyone here has done something similar and what the best way to go about this is. UltimateIy, I will have to save the past 4 gamestates and raised event caches so that a player can show a replay of the other players moves while he was disconnected, but only for the turns made after his last turn (if that makes sense). Thanks in advanced for any replies.
0
Best Answers
-
Hi @LaundryOnMyAbs,
Thank you for choosing Photon!
Here is the recommended workflow for async. games using Photon:
A- Use Photon WebHooks to save and load room state "as is" (you can "strip" unnecessary stuff as shown in the docs). Once your async. join or rejoin a room, cached events, interest groups and room/actor properties are reloaded as is. So you should rely mainly on cached events and room/actor properties to save the room data. In your case: positions, health, characters in-game...
B- Use Photon WebRPC or your own HTTP client to query the list of games per player from your backend. (e.g. "GetGameList WebRPC") We think Lobby Properties are what should be visible to the player from outside the rooms.
A ==> everything is handled by Photon for you. Photon server automatically and implicitly communicates with your backend. You just call Photon operations.
B ==> you explicitly interact with your backend either directly or via Photon's WebRPCs.5 -
1. yes, cached events, if any and if not cleaned up, will be (re)sent to the (re)joining client if it should receive them.
2. if you want this to be done using method B then you should no longer cache events using Photon and instead: once joined, send a request to your web server to request specific data for replay. so this on-demand diff data should also be saved somehow...maybe using PathEvent or PathProperties webhooks or even another explicit request.
3. yes you need an external web server. You could try Heroku, Google Cloud, AWS, etc.
Do you have like rounds or turns where you can cache a set of events independent of each other?
Meaning player 1 can rejoin a room and receive cached events of round/turn X while player 2 can join a room and receive cached events of round/turn Y?
How big can the cached events go?
Do you plan to clean up cached events at some point?
Read about:5
Answers
-
Hi @LaundryOnMyAbs,
Thank you for choosing Photon!
Here is the recommended workflow for async. games using Photon:
A- Use Photon WebHooks to save and load room state "as is" (you can "strip" unnecessary stuff as shown in the docs). Once your async. join or rejoin a room, cached events, interest groups and room/actor properties are reloaded as is. So you should rely mainly on cached events and room/actor properties to save the room data. In your case: positions, health, characters in-game...
B- Use Photon WebRPC or your own HTTP client to query the list of games per player from your backend. (e.g. "GetGameList WebRPC") We think Lobby Properties are what should be visible to the player from outside the rooms.
A ==> everything is handled by Photon for you. Photon server automatically and implicitly communicates with your backend. You just call Photon operations.
B ==> you explicitly interact with your backend either directly or via Photon's WebRPCs.5 -
Thank you for the reply.. Just a couple of simple questions and then I will figure the rest out.
1. I have to cache events by setting each raised event to cached=true (or something like that) but say these events are coroutines (shows multiple animations, walking, etc. over 5seconds), will every cached event play out when a player rejoins/joins? Or will it do everything instantly and the players client will skip ahead to the final scene state?
2. I want to let a player be able to view a replay of the previous other 3 players turns (either while he was away or even if he watched them all in real time). Would method B be better because I would need to store 2 GameStates as well as the cached events between them?
3. In option A, I still need my own external web service yes? Or is that what photon cloud is meant for.. If so, (I feel as though i should know this but ive never actually done it before), whats something I should research to find/implement a good external web service and get a http address to send a post to?
Thanks in advanced, you guys are great help!
0 -
1. yes, cached events, if any and if not cleaned up, will be (re)sent to the (re)joining client if it should receive them.
2. if you want this to be done using method B then you should no longer cache events using Photon and instead: once joined, send a request to your web server to request specific data for replay. so this on-demand diff data should also be saved somehow...maybe using PathEvent or PathProperties webhooks or even another explicit request.
3. yes you need an external web server. You could try Heroku, Google Cloud, AWS, etc.
Do you have like rounds or turns where you can cache a set of events independent of each other?
Meaning player 1 can rejoin a room and receive cached events of round/turn X while player 2 can join a room and receive cached events of round/turn Y?
How big can the cached events go?
Do you plan to clean up cached events at some point?
Read about:5 -
Yes, my game is round/turn based like a board game, but each turn a player can click their characters to move them, shoot, take cover, xtc. I use coroutines to move players on screen over time. The plan is to have a player rejoin, and get the events sent for the turns after he left (if he leaves half way through turn 3, he will come back and get events from the second part of turn 2 and turn 3 up to his turn). This means cached events can be cleaned every 5th move, Meaning a full turn has passed.
I guess my question about the replay functionality is, using method A, is it possible to reset the game board and send the cached events again ( via a replay button like "see previous turn" button) It seems to me that this is impossible using method A so i have to use method B to establish the previous game/scene state so that resending the cache would basically just repeat the entire process live, for however many times the player chooses.
As of right now, my EventsRaised are very small, but invoke alot of different methods locally based on the event code. Is this good practice? or is it better to have the raiseEvent contain most of the code within its body. Thanks for the reply again.
0 -
There is a hidden feature in Photon's cached events called "Slices".
This feature allows you to split the events cache into slices and explicitly choose which slice you want to receive cached events from when you join and once inside the room you can also switch or modify or update the slice(s).
So maybe a single slice could be mapped to a round or turn in your game.
This feature is not implemented in PUN and not documented and I have no guarantees but I can try it with you if you convince me it's worth it.
What's the maximum number of events can you cache in a single room?
If we are going to use the slices, how many slices? and how many cached events per slice?As of right now, my EventsRaised are very small, but invoke alot of different methods locally based on the event code. Is this good practice? or is it better to have the raiseEvent contain most of the code within its body.I hope I got what you mean right. You are saying that you have multiple methods calling RaiseEvent and you wonder if merging them into one is better? if so, I think it's ok and maybe better to have more than one method if the logic differs from one another.0 -
I've read about the slices method, and that's what I was going to try most likely, although I'm not exactly there yet. I have another question about cached events that call coroutines on an asynchronous join. I tried raising an event that calls a couroutine for a character with a certain id (given in the content object of the event). It seems that coroutines dont work using photon cached events because all the cached events are run so quickly (just my guess). As in if I call a method for a character to move/animate slowly towards a position, once hes there i raise the same event to another location. Do you have any tips for me to accomplish this? (Only running the cached events after a previous one is finished) Thanks.0
-
I've read about the slices methodyou mean somewhere else other than this thread? may I know where exactly?Do you have any tips for me to accomplish this?You should be able to tell from your game logic, which incoming events are cached or not and where cached events "start and end". So you should add some code that does something like this in the
OnEvent
callback:
- detect if received event is a "replay event" or not
- if so, enqueue event data to a queue for "replay events"
- detect when you finished receiving all expected "replay events"
- now start processing "replay events" one by one in the order you want by dequeuing them form the "replay events" queue0 -
Thanks. Ill try working on this. And found slices stuff here https://forum.photonengine.com/discussion/6613/event-cache-options0