diff --git a/.github/workflows/unity-test.yml b/.github/workflows/unity-test.yml index 774fd84..29e5088 100644 --- a/.github/workflows/unity-test.yml +++ b/.github/workflows/unity-test.yml @@ -7,7 +7,7 @@ on: pull_request: jobs: - test: + unity-testsuite: runs-on: ubuntu-latest steps: - name: Checkout repository diff --git a/.github/workflows/unity-testsuite-bindings.yml b/.github/workflows/unity-testsuite-bindings.yml index 1bfee47..442abcd 100644 --- a/.github/workflows/unity-testsuite-bindings.yml +++ b/.github/workflows/unity-testsuite-bindings.yml @@ -7,7 +7,7 @@ on: pull_request: jobs: - test: + check-testsuite-bindings: runs-on: ubuntu-latest steps: - name: Checkout repository @@ -110,7 +110,7 @@ jobs: - name: Check for changes run: | - git diff --exit-code + git diff --exit-code unity-tests~/client/Assets/Scripts/autogen continue-on-error: true - name: Fail if there are changes diff --git a/.gitignore b/.gitignore index 825b31b..42502a2 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,4 @@ obj~ # This is used for local paths to SpacetimeDB packages. /nuget.config /nuget.config.meta +.idea/ diff --git a/src/SpacetimeDBClient.cs b/src/SpacetimeDBClient.cs index 7fa8dd6..d908763 100644 --- a/src/SpacetimeDBClient.cs +++ b/src/SpacetimeDBClient.cs @@ -36,7 +36,10 @@ public DbConnection Build() } conn.Connect(token, uri, nameOrAddress, compression ?? Compression.Brotli); #if UNITY_5_3_OR_NEWER - SpacetimeDBNetworkManager.ActiveConnections.Add(conn); + if (SpacetimeDBNetworkManager._instance != null) + { + SpacetimeDBNetworkManager._instance.AddConnection(conn); + } #endif return conn; } @@ -163,7 +166,13 @@ protected DbConnectionBase() webSocket.OnMessage += OnMessageReceived; webSocket.OnSendError += a => onSendError?.Invoke(a); #if UNITY_5_3_OR_NEWER - webSocket.OnClose += (e) => SpacetimeDBNetworkManager.ActiveConnections.Remove(this); + webSocket.OnClose += (e) => + { + if (SpacetimeDBNetworkManager._instance != null) + { + SpacetimeDBNetworkManager._instance.RemoveConnection(this); + } + }; #endif networkMessageProcessThread = new Thread(PreProcessMessages); diff --git a/src/SpacetimeDBNetworkManager.cs b/src/SpacetimeDBNetworkManager.cs index ae5e2d4..379bf63 100644 --- a/src/SpacetimeDBNetworkManager.cs +++ b/src/SpacetimeDBNetworkManager.cs @@ -6,38 +6,56 @@ namespace SpacetimeDB { - // This class is only used in Unity projects. - // Attach this to a gameobject in your scene to use SpacetimeDB. - public class SpacetimeDBNetworkManager : MonoBehaviour - { - private static bool _alreadyInitialized; + // This class is only used in Unity projects. + // Attach this to a GameObject in your scene to use SpacetimeDB. + public class SpacetimeDBNetworkManager : MonoBehaviour + { + internal static SpacetimeDBNetworkManager? _instance; - public void Awake() - { - // Ensure that users don't create several SpacetimeDBNetworkManager instances. - // We're using a global (static) list of active connections and we don't want several instances to walk over it several times. - if (_alreadyInitialized) - { - throw new InvalidOperationException("SpacetimeDBNetworkManager is a singleton and should only be attached once."); - } - else - { - _alreadyInitialized = true; - } - } + public void Awake() + { + // Ensure that users don't create several SpacetimeDBNetworkManager instances. + // We're using a global (static) list of active connections and we don't want several instances to walk over it several times. + if (_instance != null) + { + throw new InvalidOperationException("SpacetimeDBNetworkManager is a singleton and should only be attached once."); + } + else + { + _instance = this; + } + } - internal static HashSet ActiveConnections = new(); + private readonly List activeConnections = new(); - private void ForEachConnection(Action action) - { - foreach (var conn in ActiveConnections) - { - action(conn); - } - } + public bool AddConnection(IDbConnection conn) + { + if (activeConnections.Contains(conn)) + { + return false; + } + activeConnections.Add(conn); + return true; - private void Update() => ForEachConnection(conn => conn.FrameTick()); - private void OnDestroy() => ForEachConnection(conn => conn.Disconnect()); - } + } + + public bool RemoveConnection(IDbConnection conn) + { + return activeConnections.Remove(conn); + } + + private void ForEachConnection(Action action) + { + // It's common to call disconnect from Update, which will then modify the ActiveConnections collection, + // therefore we must reverse-iterate the list of connections. + for (var x = activeConnections.Count - 1; x >= 0; x--) + { + action(activeConnections[x]); + } + } + + private void Update() => ForEachConnection(conn => conn.FrameTick()); + private void OnDestroy() => ForEachConnection(conn => conn.Disconnect()); + } } #endif diff --git a/unity-tests~ b/unity-tests~ index 75047b5..386db35 160000 --- a/unity-tests~ +++ b/unity-tests~ @@ -1 +1 @@ -Subproject commit 75047b5e58a67ba8e3b652dab17ddde61b661989 +Subproject commit 386db35877caa84a6d8842cde1e8d1a823c7fd78