Detect other player has QUIT the application, not just disconnected
The whole answer can be found below.
Try Our
Documentation
Please check if you can find an answer in our extensive documentation on PUN.
Join Us
on Discord
Meet and talk to our staff and the entire Photon-Community via Discord.
Read More on
Stack Overflow
Find more information on Stack Overflow (for Circle members only).
Detect other player has QUIT the application, not just disconnected
dango528
2019-02-22 10:05:07
Hello,
I'm trying to implement a reconnect feature to our game. It's a 1v1 game so have 2 players in a room. So far, I can detect when the player gets disconnected due to a network issue using OnDisconnected()
and OnPlayerLeftRoom()
, and display a dialog while waiting for the other player to reconnect. However, I want to detect when the other player actually quits the application, and have the remaining player win immediately. Currently, I don't know of a way to distinguish whether the other player just got disconnected or has actually quit the application. Because of this, when the other player quits the application, the remaining player gets the waiting to reconnect dialog instead of winning immediately. I thought of implementing OnApplicationQuit()
, thinking I would send an event to the remaining player before the application is closed, but more often than not by the time OnApplicationQuit()
is called, Photon has already been disconnected, so I can't send events anymore. What should be the right approach to this? Thanks
Comments
Hi @dango528,
Thank you for choosing Photon!
It depends on what you mean by quit:
- if you mean the player closed the app (or moved it to the background): you need a special event yes
void OnApplicationQuit()
{
this.SendQuitEvent();
}
// optional
void OnApplicationPause(bool paused)
{
if (paused)
{
this.SendQuitEvent();
}
}
// optional
void OnApplicationFocus(bool focused)
{
if (!focused)
{
this.SendQuitEvent();
}
}
void SendQuitEvent()
{
// send event, add your code here
PhotonNetwork.SendAllOutgoingCommands(); // send it right now
}
- if you use PlayerTTL and you have a game logic for abandoning the game:
PhotonNetwork.LeaveRoom(roomName, false)
vs. leaving temporarilyPhotonNetwork.LeaveRoom(roomName, true)
or unexepected disconnects, then you get separate callbacks for this or you can checkIsInactive
property of the player who disconnected.
Hi JohnTube,
Thanks for the reply. I tried out #1, but it doesn't work because I am trying to send an event by PhotonNetwork.RaiseEvent()
to the other player and by the time I try to do that Photon has already been disconnected and the player has left the room. It gives a warning
OnDisconnected()
and the logs indicate that I got disconnected by DisconnectByClientLogic before I can RaiseEvent()
.
As for #2, I don't have a logic for leaving the room manually.
What are my options?
Hi @dango528,
RaiseEvent()
before calling Disconnect()
. The player is quitting the room because a call to Disconnect()
is made somewhere in the code. Look in your own code for all calls to Disconnect()
first and put RaiseEvent()
call before it.
Hi @JohnTube ,
Sorry I must have lacked some key information. I am not calling Disconnect()
manually through code, instead, it gets called automatically when I force quit the app through my device (mobile - closing the app instance) or in Unity (stopping the game in Editor). I see how if I quit the game through some exit mechanism, like an exit button or so, then I can handle the cases as usual, but that is not the case. I've also tried commenting out the this.Client.Disconnect();
line in Photon's ConnectionStatusHandler#OnApplicationQuit()
to see if anything changes, but to no avail.
Thanks!
I see.
This is rather a timing issue, a race condition of sort, or rather "script execution order" as Unity calls it.
You can try to delay PUN scripts or make your own script run first.
Then I invite @Tobias to give us his opinion about this.
How can we raise an event when the application is quitting before PUN automatically calls Disconnect.
Thanks for the responses @JohnTube , looking forward to Tobias' opinions :smile:
Tricky.
We disconnect on Quit, because otherwise the Unity Editor freezes. A built client typically doesn't freeze but the disconnect makes sure that anyone in a room knows quickly that this client left.
So, we want to disconnect on quit. On disconnect, the client discards any locally queued commands and sends only the disconnect on it's own.
So, to send anything briefly before this happens, you have to make sure your script runs earlier than ours. Set this up with the execution order in Unity. Also, you have to write the message (RPC or RaiseEvent) and send it right away. For the latter, use SendAllOutgoingCommands()
.
This should work in most cases. Why just most? Because the client is still shutting down and if the message should get lost, then nobody is around to repeat it. This can't be avoided technically, unless you would wait for this message to be acknowledged (by the server, who is the receiver in this case).
Hope that helps.
Hi @Tobias ,
I'll see what I can come up with then. For now I guess I'm stuck for a while...
Thanks for the input!
Hi @Tobias ,
When you say make sure my script runs earlier than yours, what script specifically are you talking about? Since I saw the Client.Disconnect();
in Connection in Photon.Realtime.ConnectionHandler
, I'm assuming it's that. I set the script execution order to make my script go before ConnectionHandler, but the Disconnect is still happening before OnApplicationQuit()
Hi @dango528,
In PUN2 PhotonHandler
is used which extends ConnectionHandler
.
Hi @JohnTube , @Tobias
I've set my Script Execution Order to this setting
- MyScript: -90
- Photon.Pun.PhotonHandler: 50 (Default Time)
But I still get disconnected first before I can send an event in MyScript
For now I guess I can set this as a limitation...
Thanks!
Hi @Tobias , @JohnTube
Currently we are having this limitation and our game needs it badly. We have PlayerTTL greater than 0 and have custom disconnection management where we give the player an amount of time to reconnect.
However we want to call OpleaveRoom with inactive false OnApplicationQuit.
Is there a workaround for that?
OnApplicationQuit, you can't do all that much, as the process stops more or less right away.
What you can do is to call OnLeaveRoom(false) and then SendOutgoingCommands(). Unless you have a long send queue, this will send the leave right away. But: As the app closes, there will not be a repeat should this one message get lost.