How to Disconnect player from room in a proper way.

Options

Hey,

I have a room created with:

await runner.StartGame(new StartGameArgs()
{
    GameMode = mode,
    SessionName = "TestRoom",
    Scene = SceneManager.GetActiveScene().buildIndex,
    SceneManager = gameObject.AddComponent<NetworkSceneManagerDefault>()
});

where mode is

GameMode.AutoHostOrClient

When the game is finished then the player can leave room. There are two cases:

  1. Host is leaving the room, then room should be terminated.
  2. Client is leaving the room, then room should be still alive.

In both cases disconnected player/players should be despawned on both host and corresponding client (so if I disconnect as a Client then on my side there should be no players, on Host side should be one player left, if I disconnect as a Host then both sides should have no players).

Closest I've got is:

[Rpc(sources: RpcSources.All, targets: RpcTargets.StateAuthority, HostMode = RpcHostMode.SourceIsHostPlayer)]
private void RPC_RequestDisconnect(RpcInfo info = default)
{
    NetworkRunner runner = NetworkRunner.GetRunnerForScene(SceneManager.GetActiveScene());
    runner.Disconnect(info.Source);
}

public void RequestDisconnect()
{
    RPC_RequestDisconnect();
}

and this

public void OnPlayerLeft(NetworkRunner runner, PlayerRef player)
{    
    if (_runner.IsServer && _spawnedCharacters.TryGetValue(player, out NetworkObject networkObject))
    {
        runner.Despawn(networkObject);
        _spawnedCharacters.Remove(player);
    }
}

but it works in half in just one case - client requested to disconnect and client player is removed from server (but on client side there are still 2 players visible). When host disconnect everything is falling apart.

How to do this in a proper way?

Best Answer

  • WARdd
    WARdd ✭✭
    Answer ✓
    Options

    This approach I think doesn't make sense, a client doesn't need to request the host if they're allowed to leave, unless there is some sort of early-leaving penalty you need to square with the server. But more likely the player should be able to quit at any time and leave the server to figure out the details, especially since players can just lose a connection for whatever reason.

    The way I do it I have a function to despawn a player with some logic like

    if (isSelf)

    Runner.Shutdown();

    So if the player wants to leave they despawn their own player and the Runner shutdown gets triggered.

    Depending on how your project is structured you can just directly call Runner.Shutdown().

    Then all the code to open the menu and so on is in my NetworkLauncher that has INetworkRunnerCallbacks. The code should be in

    public void OnShutdown(NetworkRunner runner, ShutdownReason shutdownReason) {

    ..

    }

    That way you can correctly go back to the menu no matter for what reason the match is being shut down, which can be a lot of different reasons.

    Runner.Disconnect I only use in the opposite situation; as a back up when trying to kick a player. Basically I use a custom RPC that tells a client to leave for a specific reason. If the client is still there after n seconds the server just forcefully disconnects them with Runner.Disconnect

Answers

  • WARdd
    WARdd ✭✭
    Answer ✓
    Options

    This approach I think doesn't make sense, a client doesn't need to request the host if they're allowed to leave, unless there is some sort of early-leaving penalty you need to square with the server. But more likely the player should be able to quit at any time and leave the server to figure out the details, especially since players can just lose a connection for whatever reason.

    The way I do it I have a function to despawn a player with some logic like

    if (isSelf)

    Runner.Shutdown();

    So if the player wants to leave they despawn their own player and the Runner shutdown gets triggered.

    Depending on how your project is structured you can just directly call Runner.Shutdown().

    Then all the code to open the menu and so on is in my NetworkLauncher that has INetworkRunnerCallbacks. The code should be in

    public void OnShutdown(NetworkRunner runner, ShutdownReason shutdownReason) {

    ..

    }

    That way you can correctly go back to the menu no matter for what reason the match is being shut down, which can be a lot of different reasons.

    Runner.Disconnect I only use in the opposite situation; as a back up when trying to kick a player. Basically I use a custom RPC that tells a client to leave for a specific reason. If the client is still there after n seconds the server just forcefully disconnects them with Runner.Disconnect

  • Xenix
    Options

    Thanks, works great!