Skip to content

Commit

Permalink
feat: new virtual OnStopServer called when object is unspawned (#1743)
Browse files Browse the repository at this point in the history
  • Loading branch information
paulpach committed Apr 20, 2020
1 parent 86ac5ad commit d1695dd
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 0 deletions.
6 changes: 6 additions & 0 deletions Assets/Mirror/Runtime/NetworkBehaviour.cs
Expand Up @@ -840,6 +840,12 @@ public virtual void OnStopClient()
/// </summary>
public virtual void OnStartServer() { }

/// <summary>
/// Invoked on the server when the object is unspawned
/// <para>Useful for saving object data in persistant storage</para>
/// </summary>
public virtual void OnStopServer() { }

/// <summary>
/// Called on every NetworkBehaviour when it is activated on a client.
/// <para>Objects on the host have this function called, as there is a local client on the host. The values of SyncVars on object are guaranteed to be initialized correctly with the latest state from the server when this function is called on the client.</para>
Expand Down
20 changes: 20 additions & 0 deletions Assets/Mirror/Runtime/NetworkIdentity.cs
Expand Up @@ -598,6 +598,26 @@ internal void OnStartServer()
}
}

internal void OnStopServer()
{
foreach (NetworkBehaviour comp in NetworkBehaviours)
{
// an exception in OnStartServer 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.OnStopServer();
}
catch (Exception e)
{
Debug.LogError("Exception in OnStopServer:" + e.Message + " " + e.StackTrace);
}
}
}

bool clientStarted;
internal void OnStartClient()
{
Expand Down
2 changes: 2 additions & 0 deletions Assets/Mirror/Runtime/NetworkServer.cs
Expand Up @@ -1094,6 +1094,8 @@ static void DestroyObject(NetworkIdentity identity, bool destroyServerObject)
identity.OnStopClient();
}

identity.OnStopServer();

// when unspawning, dont destroy the server's object
if (destroyServerObject)
{
Expand Down
48 changes: 48 additions & 0 deletions Assets/Mirror/Tests/Editor/NetworkIdentityTests.cs
Expand Up @@ -105,6 +105,22 @@ class NetworkDestroyCalledNetworkBehaviour : NetworkBehaviour
public override void OnStopClient() { ++called; }
}

class StopServerCalledNetworkBehaviour : NetworkBehaviour
{
public int called;
public override void OnStopServer() { ++called; }
}

class StopServerExceptionNetworkBehaviour : NetworkBehaviour
{
public int called;
public override void OnStopServer()
{
++called;
throw new Exception("some exception");
}
}

class SetHostVisibilityExceptionNetworkBehaviour : NetworkVisibility
{
public int called;
Expand Down Expand Up @@ -1038,6 +1054,38 @@ public void OnNetworkDestroy()
Assert.That(comp.called, Is.EqualTo(1));
}

[Test]
public void OnStopServer()
{
// add components
StopServerCalledNetworkBehaviour comp = gameObject.AddComponent<StopServerCalledNetworkBehaviour>();

// make sure our test values are set to 0
Assert.That(comp.called, Is.EqualTo(0));

identity.OnStopServer();
Assert.That(comp.called, Is.EqualTo(1));
}

[Test]
public void OnStopServerEx()
{
// add components
StopServerExceptionNetworkBehaviour compEx = gameObject.AddComponent<StopServerExceptionNetworkBehaviour>();

// make sure our test values are set to 0
Assert.That(compEx.called, Is.EqualTo(0));

// call OnNetworkDestroy in identity
// one component will throw an exception, but that shouldn't stop
// OnNetworkDestroy from being called in the second one
// exception will log an error
LogAssert.ignoreFailingMessages = true;
identity.OnStopServer();
LogAssert.ignoreFailingMessages = false;
Assert.That(compEx.called, Is.EqualTo(1));
}

[Test]
public void AddObserver()
{
Expand Down

0 comments on commit d1695dd

Please sign in to comment.