How to add a "Bot" player to a lobby?

Greetings,

TL/DR getting “request failed validation” when trying to add a “bot” player to a lobby. Basically, the same player that created the lobby is trying to add another player that will be AI controlled.

I’ve got a pretty complete real-time, cross-platform, multiplayer card game working with NetCode for GameObjects, Lobby and Relay.

I want to add the ability for the player who created the lobby to add “bot” players.

I created the lobby via the usual means:

    public static async Task CreateLobbyWithAllocation(LobbyData lobbyData)
    {
        try
        {
            // Create a relay allocation and generate a join code to share with the lobby
            Debug.Log($"RelayService.Instance.CreateAllocationAsync(maxPlayers: {lobbyData.MaxPlayers});");
            var a = await RelayService.Instance.CreateAllocationAsync(lobbyData.MaxPlayers);
            Debug.Log($"RelayService.Instance.GetJoinCodeAsync(allocationId: {a.AllocationId});");
            var joinCode = await RelayService.Instance.GetJoinCodeAsync(a.AllocationId);

            // Create a lobby, adding the relay join code to the lobby data
            var options = new CreateLobbyOptions
            {
                Player = CurrentPlayer,
                Data = new Dictionary<string, DataObject>
                {
                    { Constants.JoinKey, new DataObject(DataObject.VisibilityOptions.Member, joinCode) },
                    {
                        Constants.GameStateKey,
                        new DataObject(DataObject.VisibilityOptions.Public, GameState.WaitingForPlayers.ToString())
                    },
                    {
                        Constants.ProtocolVersionKey,
                        new DataObject(DataObject.VisibilityOptions.Public, Application.version)
                    }
                },
                IsPrivate = lobbyData.Private
            };

            CurrentLobby = await Lobbies.Instance.CreateLobbyAsync(lobbyData.Name, lobbyData.MaxPlayers, options);

            Transport.SetHostRelayData(a.RelayServer.IpV4, (ushort)a.RelayServer.Port, a.AllocationIdBytes, a.Key,  a.ConnectionData);

            Heartbeat();
            PeriodicallyRefreshLobby();
        }
        catch (Exception exception)
        {
            Debug.LogError($"Error creating lobby {lobbyData.Name}.\n{exception}");
        }
    }

To add a “bot” I’m simply creating a new player object, giving it a name and a portrait index and appending an integer to its client id:

    static Player CreateBotPlayer()
    {
        var botIndex = CurrentLobby.GetRandomBotIndex();
        var playerName = PlayerExtensions.BotNames[botIndex];
        var clientId = $"{NetworkManager.Singleton.LocalClientId.ToString()}-{botIndex:smile:2}";
        return new Player(
            $"BotPlayer{botIndex}",
            null,
            new Dictionary<string, PlayerDataObject>
            {
                {Constants.ClientIdKey, new PlayerDataObject(PlayerDataObject.VisibilityOptions.Public, clientId)},
                {Constants.PlayerNameKey, new PlayerDataObject(PlayerDataObject.VisibilityOptions.Public, playerName)},
                {Constants.PlayerPortraitKey, new PlayerDataObject(PlayerDataObject.VisibilityOptions.Public, botIndex.ToString())}
            });
    }

And adding it to the lobby as follows:

    public static async Task AddBotPlayer()
    {
        try
        {
            await Lobbies.Instance.JoinLobbyByIdAsync(CurrentLobby.Id, new JoinLobbyByIdOptions
            {
                Player = CreateBotPlayer()
            });
        }
        catch (Exception e)
        {
            Debug.LogError($"Failed to add bot player {CurrentLobby?.Name}: {e}");
        }
    }

This is failing with the following (not very informative) error:

Failed to add bot player Duncan’s game: Unity.Services.Lobbies.LobbyServiceException: request failed validation —> Unity.Services.Lobbies.Http.HttpException1[Unity.Services.Lobbies.Models.ErrorStatus]: HTTP/1.1 400 Bad Request at Unity.Services.Lobbies.Http.ResponseHandler.HandleAsyncResponse (Unity.Services.Lobbies.Http.HttpClientResponse response, System.Collections.Generic.Dictionary2[TKey,TValue] statusCodeToTypeMap) [0x0007b] in F:\dev\Unity Projects\Highland Panic Root\ios_release\Library\PackageCache\com.unity.services.lobby@1.0.3\Runtime\Http\ResponseHandler.cs:95
at Unity.Services.Lobbies.Http.ResponseHandler.HandleAsyncResponse[T] (Unity.Services.Lobbies.Http.HttpClientResponse response, System.Collections.Generic.Dictionary2[TKey,TValue] statusCodeToTypeMap) [0x00001] in F:\dev\Unity Projects\Highland Panic Root\ios_release\Library\PackageCache\com.unity.services.lobby@1.0.3\Runtime\Http\ResponseHandler.cs:186 at Unity.Services.Lobbies.Apis.Lobby.LobbyApiClient.JoinLobbyByIdAsync (Unity.Services.Lobbies.Lobby.JoinLobbyByIdRequest request, Unity.Services.Lobbies.Configuration operationConfiguration) [0x001bb] in F:\dev\Unity Projects\Highland Panic Root\ios_release\Library\PackageCache\com.unity.services.lobby@1.0.3\Runtime\Apis\LobbyApi.cs:396 at Unity.Services.Lobbies.Internal.WrappedLobbyService.TryCatchRequest[TRequest,TReturn] (System.Func3[T1,T2,TResult] func, TRequest request) [0x00046] in F:\dev\Unity Projects\Highland Panic Root\ios_release\Library\PackageCache\com.unity.services.lobby@1.0.3\Runtime\SDK\WrappedLobbyService.cs:355
— End of inner exception stack trace —
at Unity.Services.Lobbies.Internal.WrappedLobbyService.ResolveErrorWrapping (Unity.Services.Lobbies.LobbyExceptionReason reason, System.Exception exception) [0x000a1] in F:\dev\Unity Projects\Highland Panic Root\ios_release\Library\PackageCache\com.unity.services.lobby@1.0.3\Runtime\SDK\WrappedLobbyService.cs:411
at Unity.Services.Lobbies.Internal.WrappedLobbyService.TryCatchRequest[TRequest,TReturn] (System.Func`3[T1,T2,TResult] func, TRequest request) [0x000c3] in F:\dev\Unity Projects\Highland Panic Root\ios_release\Library\PackageCache\com.unity.services.lobby@1.0.3\Runtime\SDK\WrappedLobbyService.cs:359
at Unity.Services.Lobbies.Internal.WrappedLobbyService.JoinLobbyByIdAsync (System.String lobbyId, Unity.Services.Lobbies.JoinLobbyByIdOptions options) [0x000a3] in F:\dev\Unity Projects\Highland Panic Root\ios_release\Library\PackageCache\com.unity.services.lobby@1.0.3\Runtime\SDK\WrappedLobbyService.cs:165
at Unity.Services.Lobbies.Internal.WrappedLobbyService.JoinLobbyByIdAsync (System.String lobbyId, Unity.Services.Lobbies.JoinLobbyByIdOptions options) [0x00234] in F:\dev\Unity Projects\Highland Panic Root\ios_release\Library\PackageCache\com.unity.services.lobby@1.0.3\Runtime\SDK\WrappedLobbyService.cs:179
at MatchmakingService.AddBotPlayer () [0x00043] in F:\dev\Unity Projects\Highland Panic Root\ios_release\Assets_highlandPanic\Lobby\Scripts\MatchmakingService.cs:167
UnityEngine.Debug:LogError (object)

Actually, you don’t add bot players to the lobby, you just try to add yourself to the lobby for the second time.
And it gives an error because you are already in the lobby.

The “CreateBotPlayer()” method only creates a Player data, not a new player.

I’ve never tried to create a bot player before but you should try NetworkPrefab to create bot player.

How would you use NetworkPrefab with Lobby services? That seems more like a Netcode for GameObjects thing.

I thought you added Netcode for GameObject to your project, didn’t you?
If you want to add AI on Lobby, you can prefer Lobby data.

First of all, thank you for responding. Second, sorry for the confusion.

Yes, I am using Netcode for GameObjects but that is for the “game play” portion of the game. The problem I am trying to solve is how to add non-human players to a lobby and have that be visible to players who have not yet joined any game. i.e. the lobby list should reflect the number of players (including bots) in any given game so the client can know whether or not to enable the Join button on the game (you can’t join a full lobby).

Since the players have not yet joined the game Netcode for GameObjects is not an option.

It sounds like my only option is to use lobby data (i.e. add a DataObject) for each “bot” added to the game which was my initial approach but that seems kludgy to me which I why I reached out to the community to see how others go about doing this.

I am certainly not the first person to add bots to their game :slight_smile:

I had thought there might be a way to add additional players to the Lobby but it’s looking more and more like that’s not possible.

Yes, that was clear explanation :slight_smile:
When I was working with PUN I also used Bot players and I added Bot players to the lobby properties. I wasn’t able to change lobby data’s max player count or player count variables at runtime.

1 Like

Thanks. Leaving this thread open in case anyone else wants to chime in.

1 Like