Detect other player has QUIT the application, not just disconnected

The whole answer can be found below.

Please note: The Photon forum is closed permanently. After many dedicated years of service we have made the decision to retire our forum and switch to read-only: we've saved the best to last! And we offer you support through these channels:

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).

Write Us
an E-Mail

Feel free to send your question directly to our developers.

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

JohnTube
2019-02-22 10:32:39

Hi @dango528,

Thank you for choosing Photon!

It depends on what you mean by quit:

  1. 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  
}
  1. if you use PlayerTTL and you have a game logic for abandoning the game: PhotonNetwork.LeaveRoom(roomName, false) vs. leaving temporarily PhotonNetwork.LeaveRoom(roomName, true) or unexepected disconnects, then you get separate callbacks for this or you can check IsInactive property of the player who disconnected.

dango528
2019-02-22 10:49:37

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

"Your event is not being sent! Check if you are in a Room and the eventCode must be less than 200"
, and my eventCode is definitely way less than 200. I even implemented 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?

JohnTube
2019-02-22 11:05:03

Hi @dango528,

by the time I try to do that Photon has already been disconnected and the player has left the room
the logs indicate that I got disconnected by DisconnectByClientLogic
You should call 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.

dango528
2019-02-22 11:10:25

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!

JohnTube
2019-02-22 11:19:39

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.

dango528
2019-02-22 11:28:22

Thanks for the responses @JohnTube , looking forward to Tobias' opinions :smile:

Tobias
2019-02-22 11:44:18

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.

dango528
2019-02-22 11:56:15

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!

dango528
2019-02-22 12:34:03

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()

JohnTube
2019-02-26 12:54:16

Hi @dango528,

In PUN2 PhotonHandler is used which extends ConnectionHandler.

dango528
2019-02-28 06:47:44

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!

Oddreams
2020-10-09 12:20:27

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?

Tobias
2020-11-03 10:27:33

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.

Back to top