Skip to main content
Notice removed Draw attention by Simone Chelo
Bounty Ended with TurtleKwitty's answer chosen by Simone Chelo
Tweeted twitter.com/StackGameDev/status/1030197847516438529
even if one of the platforms i support is mobile, the question is not dependant on this factor (that is still mentioned in the text)
Link
Notice added Draw attention by Simone Chelo
Bounty Started worth 50 reputation by Simone Chelo
Source Link

Enter in a match that is already started

In my Unity mobile game, I need multiplayer online functionalities. All the players should be visible in the world at any given time (of course, with some filtering), and a player should be able to connect at any time. Let's say that, for the purpose of this question, only 100 players at the time will log into the game.

My first try involved using Unity's built-in NetworkManager, but the two problems that arose are that:

  1. One player is always the host, meaning that if that player logs out all the other players.
  2. I did not manage to make it work on two different networks.

The implementation I used comes from this tutorial.

Next try was using an extension of NetworkLobbyManager, that allows through the Matchmaking system to solve problem 2.

This is my implementation:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Networking.Match;
using UnityEngine.SceneManagement;

public class AutoLobbyManager : NetworkLobbyManager {

    protected int currentPage = 0;
    protected int previousPage = 0;

    public void CreateOrJoin() {
        StartMatchMaker();
        RequestPage(0);
    }

    public void OnMatchListReceived(bool success, string extendedInfo, List<MatchInfoSnapshot> matches)
    {
        if (matches.Count == 0) {
            // Server does not exist yet. Create one.
            CreateMatch();
            return;
        } 

        // There is then a server. Join it.
        JoinMatch(matches[0]);


    }

    public void RequestPage(int page) {
        matchMaker.ListMatches(page, 1, "", true, 0, 0, OnMatchListReceived);
    }


    public void CreateMatch() {
        matchMaker.CreateMatch( "Main Match", (uint)maxPlayers, true, "", "", "", 0, 0, OnMatchCreate);
    }


    void JoinMatch(MatchInfoSnapshot match) {
        matchMaker.JoinMatch(match.networkId, "", "", "", 0, 0, OnMatchJoined);
    }


    public override void OnMatchCreate(bool success, string extendedInfo, MatchInfo matchInfo) {
        base.OnMatchCreate(success, extendedInfo, matchInfo);
        Debug.Log("Match created!");
        ServerChangeScene(playScene);
    }

     public override void OnClientSceneChanged(NetworkConnection conn) {
         string loadedSceneName = SceneManager.GetSceneAt(0).name;
         if (loadedSceneName == lobbyScene) {
           if (client.isConnected)
               CallOnClientEnterLobby();
         } else {
           CallOnClientExitLobby();
         }

         OnLobbyClientSceneChanged(conn);
    }

    void CallOnClientEnterLobby() {
        OnLobbyClientEnter();
        foreach (var player in lobbySlots)
        {
            if (player == null)
                continue;

            player.readyToBegin = false;
            player.OnClientEnterLobby();
        }
    }

    void CallOnClientExitLobby() {
        OnLobbyClientExit();
        foreach (var player in lobbySlots)
        {
            if (player == null)
                continue;

            player.OnClientExitLobby();
        }
    }

}

This makes possible to create a Lobby if there is no Lobby, and join the first if there is. It works, if we remove the highlighted line here:

public override void OnMatchCreate(bool success, string extendedInfo, 
MatchInfo matchInfo) {
    base.OnMatchCreate(success, extendedInfo, matchInfo);
    Debug.Log("Match created!");
    ***** ServerChangeScene(playScene); *****
}

Because this starts the game. If that line is activated (since I want to start the game as soon as possible), when a client tries to connect, the Server logs:

NetworkLobbyManager can't accept new connection [hostId: 0 connectionId: 1 isReady: False channel count: 2], not in lobby and game already in progress.

And the client is not added to the game. I understand that lobbies usually work like that, but:

1. Is it possible to add a client after a game is added, with NetworkLobbyManager?

2. Is it the right approach to achieve a multiplayer, non-lobby-based, non-host-based, online game in Unity?