Exception in OnStopServer

Not sure if this issue is just for me or in your code too. Your video didn’t show you attempting what is causing my error. Basically, if I kill a base and then click to leave the game, and then replay, if I kill the same base I get this error.

The first kill always works fine. Also, if I kill the other base in round 2, it works fine. It only happens when I kill a base for the 2nd time.

Ive spent hours trying to solve it with no success, but the exception is raised in NetworkIdentity.cs line 733. Which is called when we handle the death of the UnitBase (NetworkServer.Destroy(gameObject);). Its possible its related to the static event being cached between the scenes, but I cant figure it out.

The exception message is:

Exception in OnStopServer:The object of type 'GameOverHandler' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.   at (wrapper managed-to-native) UnityEngine.Object.GetName(UnityEngine.Object)
  at UnityEngine.Object.get_name () [0x00001] in <052502435982472d92da7f939c7f8164>:0 
  at Mirror.NetworkBehaviour.SendRPCInternal (System.Type invokeClass, System.String rpcName, Mirror.NetworkWriter writer, System.Int32 channelId, System.Boolean excludeOwner) [0x0002a] in D:\Unity Projects 2\RealTimeStrategyNetworking\Assets\Mirror\Runtime\NetworkBehaviour.cs:228 
  at GameOverHandler.RpcGameOver (System.String winner) [0x00010] in <25519ec8f69b43deab92f83f59e979e1>:0 
  at GameOverHandler.ServerHandleBaseDespawned (UnitBase unitBase) [0x00077] in D:\Unity Projects 2\RealTimeStrategyNetworking\Assets\Scripts\Buildings\GameOverHandler.cs:51 
  at (wrapper delegate-invoke) System.Action`1[UnitBase].invoke_void_T(UnitBase)
  at UnitBase.OnStopServer () [0x0000a] in D:\Unity Projects 2\RealTimeStrategyNetworking\Assets\Scripts\Buildings\UnitBase.cs:30 
  at Mirror.NetworkIdentity.OnStopServer () [0x0000f] in D:\Unity Projects 2\RealTimeStrategyNetworking\Assets\Mirror\Runtime\NetworkIdentity.cs:729 
UnityEngine.Logger:Log(LogType, Object)
Mirror.ILoggerExtensions:LogError(ILogger, Object) (at Assets/Mirror/Runtime/Logging/LogFactory.cs:82)
Mirror.NetworkIdentity:OnStopServer() (at Assets/Mirror/Runtime/NetworkIdentity.cs:733)
Mirror.NetworkServer:DestroyObject(NetworkIdentity, Boolean) (at Assets/Mirror/Runtime/NetworkServer.cs:1267)
Mirror.NetworkServer:Destroy(GameObject) (at Assets/Mirror/Runtime/NetworkServer.cs:1298)
UnitBase:ServerHandleDeath() (at Assets/Scripts/Buildings/UnitBase.cs:41)
Health:DealDamage(Int32) (at Assets/Scripts/Combat/Health.cs:45)
Projectile:OnTriggerEnter(Collider) (at Assets/Scripts/Combat/Projectile.cs:39)

2 Likes

I’ve encountered the same error, and I found a temporary workaround. @jjaslow is correct that it is caused by static event handlers persisting between scenes. The function OnStopServer is never called on the GameOverHandler, which means the GameOverHandler never unsubscribes from the UnitBase events. If I destroy a base, click to leave the game, and then start a second game and destroy a base, the UnitBase class invokes ServerOnBaseDespawned for two listeners. One of those listeners no longer exists because it was from the first game. The Exception is thrown when RpcGameOver is called on the object that no longer exists.

I don’t know why GameOverHandler.OnStopServer doesn’t get called when the Host stops, but my temporary workaround is to add the following line to the top of ServerHandleBaseDespawned in the GameOverHandler class.

if (this == null) { return; }

So my function now looks like this:

[Server]
private void ServerHandleBaseDespawned(UnitBase unitBase)
{
    if (this == null) { return; }

    bases.Remove(unitBase);

    if (bases.Count != 1) { return; }

    int playerId = bases[0].connectionToClient.connectionId;

    RpcGameOver($"Player {playerId}");
}
2 Likes

Thank you, this works for me also.

My final solution, which didn’t work, was to try and manually destroy the GameOverHandler instance. In the NetworkManager.OnServerSceneChanged I added

NetworkServer.Destroy(gameOverHandlerInstance.gameObject);

but never thought to ensure that the destroy was handled successfully.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms