diff --git a/Assets/Mirror/Runtime/NetworkIdentity.cs b/Assets/Mirror/Runtime/NetworkIdentity.cs index 4fa874824..d4215cb40 100644 --- a/Assets/Mirror/Runtime/NetworkIdentity.cs +++ b/Assets/Mirror/Runtime/NetworkIdentity.cs @@ -583,7 +583,19 @@ internal void OnStartLocalPlayer() foreach (NetworkBehaviour comp in NetworkBehaviours) { - comp.OnStartLocalPlayer(); + // an exception in OnStartLocalPlayer should be caught, so that + // one component's exception doesn't stop all other components + // from being initialized + // => this is what Unity does for Start() etc. too. + // one exception doesn't stop all the other Start() calls! + try + { + comp.OnStartLocalPlayer(); + } + catch (Exception e) + { + Debug.LogError("Exception in OnStartClient:" + e.Message + " " + e.StackTrace); + } } } diff --git a/Assets/Mirror/Tests/Editor/NetworkIdentityTests.cs b/Assets/Mirror/Tests/Editor/NetworkIdentityTests.cs index 6d7416f06..ac47045f4 100644 --- a/Assets/Mirror/Tests/Editor/NetworkIdentityTests.cs +++ b/Assets/Mirror/Tests/Editor/NetworkIdentityTests.cs @@ -74,6 +74,16 @@ class StopAuthorityCalledNetworkBehaviour : NetworkBehaviour public override void OnStopAuthority() { ++called; } } + class StartLocalPlayerExceptionNetworkBehaviour : NetworkBehaviour + { + public int called; + public override void OnStartLocalPlayer() + { + ++called; + throw new Exception("some exception"); + } + } + class StartLocalPlayerCalledNetworkBehaviour : NetworkBehaviour { public int called; @@ -855,16 +865,26 @@ public void OnStartLocalPlayer() // create a networkidentity with our test component GameObject gameObject = new GameObject(); NetworkIdentity identity = gameObject.AddComponent(); + StartLocalPlayerExceptionNetworkBehaviour compEx = gameObject.AddComponent(); StartLocalPlayerCalledNetworkBehaviour comp = gameObject.AddComponent(); - // call OnStartLocalPlayer on identity should call it in comp + // make sure our test values are set to 0 + Assert.That(compEx.called, Is.EqualTo(0)); Assert.That(comp.called, Is.EqualTo(0)); + + // call OnStartLocalPlayer in identity + // one component will throw an exception, but that shouldn't stop + // OnStartLocalPlayer from being called in the second one + LogAssert.ignoreFailingMessages = true; // exception will log an error identity.OnStartLocalPlayer(); + LogAssert.ignoreFailingMessages = false; + Assert.That(compEx.called, Is.EqualTo(1)); Assert.That(comp.called, Is.EqualTo(1)); // we have checks to make sure that it's only called once. // let's see if they work. identity.OnStartLocalPlayer(); + Assert.That(compEx.called, Is.EqualTo(1)); // same as before? Assert.That(comp.called, Is.EqualTo(1)); // same as before? // clean up