Skip to content

Commit

Permalink
Merge pull request #1 from UCL-VR/pr-autoreconnect
Browse files Browse the repository at this point in the history
Add scene reload, editor gui and user notification for reconnect functionality
  • Loading branch information
FJThiel authored Jul 25, 2023
2 parents 85c1f96 + 2d9e6d5 commit 0bfcafe
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 80 deletions.
2 changes: 2 additions & 0 deletions Unity/Assets/Editor/Rooms/RoomClientEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ public override void OnInspectorGUI()
EditorGUILayout.HelpBox("Joined Room " + component.Room.UUID, MessageType.Info);
}

EditorGUILayout.PropertyField(serializedObject.FindProperty("reconnectBehaviour"));

foldoutRooms = EditorGUILayout.BeginFoldoutHeaderGroup(foldoutRooms, "Available Rooms");

if (foldoutRooms)
Expand Down
15 changes: 2 additions & 13 deletions Unity/Assets/Runtime/Messaging/NetworkScene.cs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ public void AddConnection(INetworkConnection connection)
/// Public method instructing the network scene to drop all current connections and dispose of them.
/// Used to recover from a connection loss to Nexus.
/// </summary>
public void ResetConnections()
public void ClearConnections()
{
foreach (var c in connections)
{
Expand Down Expand Up @@ -349,18 +349,7 @@ public void SendJson<T>(NetworkId objectid, T message)

private void OnDestroy()
{
foreach (var c in connections)
{
try
{
c.Dispose();
}
catch
{

}
}
connections.Clear();
ClearConnections();
}
}
}
118 changes: 51 additions & 67 deletions Unity/Assets/Runtime/Rooms/RoomClient.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
using Codice.Client.Commands;
using JetBrains.Annotations;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using Ubiq.Dictionaries;
using Ubiq.Messaging;
using Ubiq.Networking;
using Ubiq.Rooms.Messages;
using Ubiq.XR.Notifications;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace Ubiq.Rooms
{
Expand Down Expand Up @@ -243,18 +241,16 @@ public IEnumerable<IPeer> Peers
public static float HeartbeatTimeout = 5f;
public static float HeartbeatInterval = 1f;

// Parameters private and public for the reconnection process.
private enum ReconnectionStatus { Off, Reset, Received, Rejoining};
private ReconnectionStatus reconnectionStatus = ReconnectionStatus.Off;
private float lastResetTime = 0;
private float timeSinceLastReset => Time.realtimeSinceStartup - lastResetTime;
private float lastRejoinTime = 0;
private float timeSinceLastRejoin => Time.realtimeSinceStartup - lastRejoinTime;
private Guid previousRoomGUID = Guid.Empty;
public static bool AttemtReconnecting = true; // Whether the RoomClient attemtps to reconnect to the server on connection loss.
public static float ReconnectTimeout = 5f; // How long a timeout can last until the reconnect procedure is triggered.
public static float ReconnectInterval = 5f; // The intervals in which reconnect attempts are done.
public static float RejoinInterval = 5f; // The intervals in which rejoin attempts are done.
public enum ReconnectBehaviour
{
None,
Reconnect,
ReconnectAndReloadScenes
}

public ReconnectBehaviour reconnectBehaviour = ReconnectBehaviour.None;
public static float reconnectTimeout = 10.0f;
private float nextReconnectTimeout = reconnectTimeout;

private PeerInterfaceFriend me = new PeerInterfaceFriend(Guid.NewGuid().ToString());
private RoomInterfaceFriend room = new RoomInterfaceFriend();
Expand All @@ -278,7 +274,15 @@ public override string Message
{
get
{
return $"No Connection ({ client.heartbeatReceived.ToString("0") } seconds ago)";
if (client.reconnectBehaviour == ReconnectBehaviour.None)
{
return $"Connection lost ({ client.heartbeatReceived.ToString("0") } seconds ago)";
}
else
{
var timeToReconnect = Mathf.Max(0,client.nextReconnectTimeout - client.heartbeatReceived);
return $"Connection lost (Next reconnect attempt in { timeToReconnect.ToString("0") } seconds)";
}
}
}
}
Expand Down Expand Up @@ -564,11 +568,6 @@ protected void ProcessMessage(ReferenceCountedSceneGraphMessage message)
{
pingReceived = Time.realtimeSinceStartup;

// Set flag for first ping after connection loss
if (reconnectionStatus == ReconnectionStatus.Reset)
reconnectionStatus = ReconnectionStatus.Received;

PlayerNotifications.Delete(ref notification);
var response = JsonUtility.FromJson<PingResponseArgs>(container.args);
OnPingResponse(response);
}
Expand Down Expand Up @@ -671,7 +670,7 @@ public void ResetAndReconnect()
public void ResetAndReconnect(ConnectionDefinition[] connectionDefinitions)
{
// Drop all connections
scene.ResetConnections();
scene.ClearConnections();

// Reconnect all connections
foreach (var item in connectionDefinitions)
Expand Down Expand Up @@ -727,55 +726,19 @@ private void Update()

if (heartbeatReceived > HeartbeatTimeout)
{
// There's been a long interval between server responses
// We may be disconnected, or there may be network issues

if (notification == null)
{
notification = PlayerNotifications.Show(new TimeoutNotification(this));
}
}

// Reconnection behaviour
// Test if dynamic reconnection is enabled
if(AttemtReconnecting)
{
// If enabled, check for current reconnection status
switch (reconnectionStatus)
if (heartbeatReceived > nextReconnectTimeout
&& reconnectBehaviour != ReconnectBehaviour.None)
{
// Reconnection off: If reconnect timeout is exceeded, old room GUID is stored, reset initiated, and next state is initiaded.
case ReconnectionStatus.Off:
if(heartbeatReceived > ReconnectTimeout)
{
previousRoomGUID = new Guid(room.UUID);
ResetAndReconnect();
lastResetTime = Time.realtimeSinceStartup;
reconnectionStatus = ReconnectionStatus.Reset;
}
break;
// Reconnection Reset: Connection is reset. While no response has been received, reset connection again in regular intervals.
case ReconnectionStatus.Reset:
if (timeSinceLastReset > ReconnectInterval)
{
ResetAndReconnect();
lastResetTime = Time.realtimeSinceStartup;
}
break;
// Reconnection Received: A response by Nexus has received. Attempt at rejoining room.
case ReconnectionStatus.Received:
Join(previousRoomGUID);
lastRejoinTime = Time.realtimeSinceStartup;
reconnectionStatus = ReconnectionStatus.Rejoining;
break;
// Reconnection Rejoining: Re-attempt rejoining room at regular intervals until succesful.
case ReconnectionStatus.Rejoining:
if(room.UUID == previousRoomGUID.ToString())
{
reconnectionStatus = ReconnectionStatus.Off;
}
else if(timeSinceLastRejoin > RejoinInterval)
{
Join(previousRoomGUID);
lastRejoinTime = Time.realtimeSinceStartup;
}
break;
ResetAndReconnect();
nextReconnectTimeout += reconnectTimeout;
}
}
}
Expand Down Expand Up @@ -857,9 +820,30 @@ public void Ping()

private void OnPingResponse(PingResponseArgs args)
{
PlayerNotifications.Delete(ref notification);
nextReconnectTimeout = reconnectTimeout;

if(SessionId != args.sessionId && SessionId != null)
{
Join(name:"",publish:false); // The RoomClient has re-established connectivity with the RoomServer, but under a different state. So, leave the room and let the user code re-establish any state.
// The RoomClient has re-established connectivity with
// the RoomServer, but under a different state.
if (reconnectBehaviour == ReconnectBehaviour.ReconnectAndReloadScenes)
{
var scenes = new Scene[SceneManager.sceneCount];
for (int i = 0; i < SceneManager.sceneCount; i++)
{
scenes[i] = SceneManager.GetSceneAt(i);
}

var first = true;
for (int i = 0; i < scenes.Length; i++)
{
SceneManager.LoadScene(scenes[i].buildIndex,mode: first
? LoadSceneMode.Single
: LoadSceneMode.Additive);
first = false;
}
}
}

SessionId = args.sessionId;
Expand Down
7 changes: 7 additions & 0 deletions Unity/Assets/Samples/Start Here.unity
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ MeshRenderer:
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
Expand Down Expand Up @@ -461,6 +462,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -1.214, y: 0.634, z: -0.99}
m_LocalScale: {x: 0.25361246, y: 0.25361246, z: 0.25361246}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 4
Expand Down Expand Up @@ -707,6 +709,11 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2642065778884258271, guid: 46c1f5d5a11cf5042886aabd56e7b9d7,
type: 3}
propertyPath: m_Enabled
value: 1
objectReference: {fileID: 0}
- target: {fileID: 2642065778884258271, guid: 46c1f5d5a11cf5042886aabd56e7b9d7,
type: 3}
propertyPath: servers.Array.size
Expand Down
7 changes: 7 additions & 0 deletions Unity/Assets/Samples/_Common/Prefabs/Network Scene.prefab
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7068762446378101729}
m_RootOrder: 4
Expand Down Expand Up @@ -72,6 +73,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7068762446378101729}
m_RootOrder: 0
Expand Down Expand Up @@ -118,6 +120,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7068762446051028576}
- {fileID: 7068762446560339092}
Expand Down Expand Up @@ -160,6 +163,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
servers:
- {fileID: -7849211376014683480, guid: 1c91df7c43c1dbe4fb0fb303e71a2790, type: 2}
reconnectBehaviour: 2
--- !u!114 &7068762446378101731
MonoBehaviour:
m_ObjectHideFlags: 0
Expand Down Expand Up @@ -217,6 +221,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7068762446378101729}
m_RootOrder: 1
Expand Down Expand Up @@ -260,6 +265,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7068762446378101729}
m_RootOrder: 2
Expand Down Expand Up @@ -309,6 +315,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7068762446378101729}
m_RootOrder: 3
Expand Down

0 comments on commit 0bfcafe

Please sign in to comment.