Skip to content

Commit a52f070

Browse files
authored
Bugfix/host quit strands some players (#288)
* fixing issue where host quitting strands some clients in the game. Also fixed issue where no disconnect message was shown in MainMenu. * adding missed meta file * removing transitionreason in favor of a new DisconnectReason class that hangs off ClientGameNetPortal * moving disconnect reset to a better place. Now it will happen even if a client decides to become a host, and regardless of whether starting as a client or relay client.
1 parent e49fa3d commit a52f070

File tree

10 files changed

+165
-19
lines changed

10 files changed

+165
-19
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
%YAML 1.1
2+
%TAG !u! tag:unity3d.com,2011:
3+
--- !u!1 &8576152884213668003
4+
GameObject:
5+
m_ObjectHideFlags: 0
6+
m_CorrespondingSourceObject: {fileID: 0}
7+
m_PrefabInstance: {fileID: 0}
8+
m_PrefabAsset: {fileID: 0}
9+
serializedVersion: 6
10+
m_Component:
11+
- component: {fileID: 8576152884213668001}
12+
- component: {fileID: 8576152884213668000}
13+
m_Layer: 0
14+
m_Name: MainMenuState
15+
m_TagString: Untagged
16+
m_Icon: {fileID: 0}
17+
m_NavMeshLayer: 0
18+
m_StaticEditorFlags: 0
19+
m_IsActive: 1
20+
--- !u!4 &8576152884213668001
21+
Transform:
22+
m_ObjectHideFlags: 0
23+
m_CorrespondingSourceObject: {fileID: 0}
24+
m_PrefabInstance: {fileID: 0}
25+
m_PrefabAsset: {fileID: 0}
26+
m_GameObject: {fileID: 8576152884213668003}
27+
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
28+
m_LocalPosition: {x: 0, y: 0, z: 0}
29+
m_LocalScale: {x: 1, y: 1, z: 1}
30+
m_Children: []
31+
m_Father: {fileID: 0}
32+
m_RootOrder: 0
33+
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
34+
--- !u!114 &8576152884213668000
35+
MonoBehaviour:
36+
m_ObjectHideFlags: 0
37+
m_CorrespondingSourceObject: {fileID: 0}
38+
m_PrefabInstance: {fileID: 0}
39+
m_PrefabAsset: {fileID: 0}
40+
m_GameObject: {fileID: 8576152884213668003}
41+
m_Enabled: 1
42+
m_EditorHideFlags: 0
43+
m_Script: {fileID: 11500000, guid: ab10fd7c6aa7d36438f5ac1c0ebfadbb, type: 3}
44+
m_Name:
45+
m_EditorClassIdentifier:

Assets/BossRoom/Prefabs/State/MainMenuState.prefab.meta

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version https://git-lfs.github.com/spec/v1
2-
oid sha256:5060647f2ae656c8a84051a839ff727d64afdd7194347967b5cd1c909f083681
3-
size 46738
2+
oid sha256:7fde64095d2daa9da6cc92ac5c7998230bbe2386a14c4179ec5bc0f0316ef26f
3+
size 49225

Assets/BossRoom/Scripts/Client/Game/State/ClientMainMenuState.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,4 @@ public override void NetworkStart()
1919
//fortunately we know you are a client, because all players are clients when sitting at the main menu screen.
2020
}
2121
}
22-
2322
}

Assets/BossRoom/Scripts/Client/Game/State/ClientPostGameState.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using UnityEngine;
2+
13
namespace BossRoom.Client
24
{
35
/// <summary>
@@ -8,6 +10,19 @@ public class ClientPostGameState : GameStateBehaviour
810
{
911
public override GameState ActiveState { get { return GameState.PostGame; } }
1012

13+
protected override void Start()
14+
{
15+
base.Start();
16+
17+
//it is common for the user to get dumped back to main menu from here (i.e., if the host decides not to play again), and
18+
//it is a little funny to display a "Connection to Host Lost" message in that case. The best thing would probably be to
19+
//display a "Host Abandoned the Game" message, but this would require some more plumbing (an RPC from the host before it quit,
20+
//containing that information).
21+
//In the meantime, we just set "UserRequested" to suppress the Disconnected error popup.
22+
var portalGO = GameObject.FindGameObjectWithTag("GameNetPortal");
23+
portalGO.GetComponent<ClientGameNetPortal>().DisconnectReason.SetDisconnectReason(DisconnectReasonType.UserRequested);
24+
}
25+
1126
public override void NetworkStart()
1227
{
1328
base.NetworkStart();

Assets/BossRoom/Scripts/Client/Net/ClientGameNetPortal.cs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ public class ClientGameNetPortal : MonoBehaviour
1818
{
1919
private GameNetPortal m_Portal;
2020

21+
/// <summary>
22+
/// If a disconnect occurred this will be populated with any contextual information that was available to explain why.
23+
/// </summary>
24+
public DisconnectReason DisconnectReason { get; private set; } = new DisconnectReason();
25+
2126
/// <summary>
2227
/// Time in seconds before the client considers a lack of server response a timeout
2328
/// </summary>
@@ -42,6 +47,8 @@ void Start()
4247

4348
private void NetworkStart()
4449
{
50+
DisconnectReason.Clear();
51+
4552
if (!m_Portal.NetManager.IsClient)
4653
{
4754
enabled = false;
@@ -54,7 +61,7 @@ private void NetworkStart()
5461
//only do this if a pure client, so as not to overlap with host behavior in ServerGameNetPortal.
5562
m_Portal.UserDisconnectRequested += OnUserDisconnectRequest;
5663
}
57-
m_Portal.NetManager.OnClientDisconnectCallback += OnClientDisconnect;
64+
5865
SceneManager.sceneLoaded += OnSceneLoaded;
5966
}
6067
}
@@ -71,23 +78,11 @@ private void OnUserDisconnectRequest()
7178
{
7279
if( m_Portal.NetManager.IsClient )
7380
{
81+
DisconnectReason.SetDisconnectReason(DisconnectReasonType.UserRequested);
7482
m_Portal.NetManager.StopClient();
7583
}
7684
}
7785

78-
/// <summary>
79-
/// Invoked whenever a client disconnects from the host.
80-
/// </summary>
81-
private void OnClientDisconnect(ulong clientId)
82-
{
83-
if( clientId == m_Portal.NetManager.LocalClientId )
84-
{
85-
SceneManager.sceneLoaded -= OnSceneLoaded;
86-
m_Portal.UserDisconnectRequested -= OnUserDisconnectRequest;
87-
m_Portal.NetManager.OnClientDisconnectCallback -= OnClientDisconnect;
88-
}
89-
}
90-
9186
private void OnConnectFinished(ConnectStatus status)
9287
{
9388
//on success, there is nothing to do (the MLAPI scene management system will take us to the next scene).
@@ -99,15 +94,25 @@ private void OnConnectFinished(ConnectStatus status)
9994

10095
private void OnDisconnectOrTimeout(ulong clientID)
10196
{
102-
if(clientID == MLAPI.NetworkManager.Singleton.LocalClientId )
97+
// we could also check whether the disconnect was us or the host, but the "interesting" question is whether
98+
//following the disconnect, we're no longer a Connected Client, so we just explicitly check that scenario.
99+
if ( !MLAPI.NetworkManager.Singleton.IsConnectedClient )
103100
{
101+
SceneManager.sceneLoaded -= OnSceneLoaded;
102+
m_Portal.UserDisconnectRequested -= OnUserDisconnectRequest;
103+
104104
//On a client disconnect we want to take them back to the main menu.
105105
//We have to check here in SceneManager if our active scene is the main menu, as if it is, it means we timed out rather than a raw disconnect;
106106
if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name != "MainMenu")
107107
{
108108
// we're not at the main menu, so we obviously had a connection before... thus, we aren't in a timeout scenario.
109109
// Just shut down networking and switch back to main menu.
110110
MLAPI.NetworkManager.Singleton.Shutdown();
111+
if( !DisconnectReason.HasTransitionReason )
112+
{
113+
//disconnect that happened for some other reason than user UI interaction--should display a message.
114+
DisconnectReason.SetDisconnectReason(DisconnectReasonType.Disconnect);
115+
}
111116
SceneManager.LoadScene("MainMenu");
112117
}
113118
else
@@ -129,7 +134,6 @@ private void OnDisconnectOrTimeout(ulong clientID)
129134
/// <param name="port">The port of the host to connect to. </param>
130135
public static void StartClient(GameNetPortal portal, string ipaddress, int port)
131136
{
132-
//DMW_NOTE: non-portable. We need to be updated when moving to UTP transport.
133137
var chosenTransport = NetworkManager.Singleton.gameObject.GetComponent<TransportPicker>().IpHostTransport;
134138
NetworkManager.Singleton.NetworkConfig.NetworkTransport = chosenTransport;
135139

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
3+
using UnityEngine;
4+
5+
namespace BossRoom.Client
6+
{
7+
/// <summary>
8+
/// enum that records additional context for why a user was disconnected. The primary use case for this
9+
/// is to allow the MainMenu to display an appropriate message after a disconnect event.
10+
/// </summary>
11+
public enum DisconnectReasonType
12+
{
13+
Undefined, //no reason has been set.
14+
UserRequested, //user explicitly requested a disconnect.
15+
Disconnect, //client unexpectedly lost connection with host.
16+
}
17+
18+
/// <summary>
19+
/// This class provides some additional context for the connection managed by the ClientGameNetPortal. If a disconnect occurrs, or is expected to occur, client
20+
/// code can set the reason why here. Then subsequent code can interrogate this class to get the disconnect reason, and display appropriate information to
21+
/// the user, even after a scene transition has occurred. The state is set back to Undefined if a new connection is begun.
22+
/// </summary>
23+
public class DisconnectReason
24+
{
25+
/// <summary>
26+
/// When a disconnect is detected (or expected), set this to provide some context for why it occurred.
27+
/// </summary>
28+
public void SetDisconnectReason( DisconnectReasonType reason)
29+
{
30+
//using an explicit setter here rather than the auto-property, to make the code locations where disconnect information is set more obvious.
31+
Reason = reason;
32+
}
33+
34+
/// <summary>
35+
/// The reason why a disconnect occurred, or Undefined if not set.
36+
/// </summary>
37+
public DisconnectReasonType Reason { get; private set; } = DisconnectReasonType.Undefined;
38+
39+
/// <summary>
40+
/// Clear the DisconnectReason, returning it to Undefined.
41+
/// </summary>
42+
public void Clear()
43+
{
44+
Reason = DisconnectReasonType.Undefined;
45+
}
46+
47+
/// <summary>
48+
/// Has a TransitionReason already be set? (The TransitionReason provides context for why someone transition back to the MainMenu, and is a one-use item
49+
/// that is unset as soon as it is read).
50+
/// </summary>
51+
public bool HasTransitionReason => Reason != DisconnectReasonType.Undefined;
52+
}
53+
}

Assets/BossRoom/Scripts/Client/Net/DisconnectReason.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/BossRoom/Scripts/Client/UI/MainMenuUI.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ void Start()
3333

3434
m_ClientNetPortal.NetworkTimedOut += OnNetworkTimeout;
3535
m_ClientNetPortal.ConnectFinished += OnConnectFinished;
36+
37+
if (m_ClientNetPortal.DisconnectReason.Reason == DisconnectReasonType.Disconnect )
38+
{
39+
m_ResponsePopup.SetupNotifierDisplay("Disconnected From Host", "The connection to the Host was lost", false, true );
40+
}
3641
}
3742

3843
public void OnHostClicked()

Packages/com.unity.multiplayer.samples.coop/Third Party Notices.md.meta

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)