Создавайте префабы в соответствии с платформой игрока с помощью LobbyManager.

Я пытаюсь создавать разные префабы в зависимости от платформы игрока. Поэтому я переопределяю NetworkLobbyManager, чтобы создавать объекты так, как я хочу. Итак, я создаю Dictionnary, который связывает connectionId с индексом префаба, а затем я создаю экземпляр префаба в соответствии с этим индексом.

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

public class LobbyManager : NetworkLobbyManager
{
    private Dictionary<int, int> m_currentPlayers;

    void Start()
    {
        m_currentPlayers = new Dictionary<int, int>();
    }

    void AddPlayer(NetworkConnection conn)
    {
        if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer)
        {
            m_currentPlayers.Add(conn.connectionId, 0);
        }
        else if (Application.platform == RuntimePlatform.Android)
        {
            m_currentPlayers.Add(conn.connectionId, 1);
        }
    }

    public override GameObject OnLobbyServerCreateLobbyPlayer(NetworkConnection conn, short playerControllerId)
    {
        AddPlayer(conn);

        return base.OnLobbyServerCreateLobbyPlayer(conn, playerControllerId);
    }

    public override GameObject OnLobbyServerCreateGamePlayer(NetworkConnection conn, short playerControllerId)
    {
        GameObject go = Instantiate(spawnPrefabs[m_currentPlayers[conn.connectionId]]);
        NetworkServer.AddPlayerForConnection(conn, go, playerControllerId);

        return go;
    }
}

Но с этим кодом спаун игрока на клиенте всегда такой же, как и на хосте, и я не знаю почему, потому что кажется, что я переопределяю правильные функции, и я видел здесь http://abrgame.blogspot.fr/2016/01/using-unet-to-spawn-other-player.html парень, который использовал ту же технику, и это работает для него...


person Kalixio    schedule 11.05.2018    source источник


Ответы (1)


Твоя проблема

if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer)
{
    m_currentPlayers.Add(conn.connectionId, 0);
}
else if (Application.platform == RuntimePlatform.Android)
{
    m_currentPlayers.Add(conn.connectionId, 1);
}

Компонент NetworkLobbyManager ведет себя по-разному при запуске в качестве клиента или хоста, но в конечном итоге, если я прав, хост обрабатывает спавн игрока. В вашем коде это означает, что компонент смотрит только на свою собственную платформу, а не на платформы подключающихся игроков.

Возможное решение

Вам необходимо передать хосту информацию о платформе подключающегося игрока. Вы можете создать производный класс NetworkConnection, который извлекает и переносит информацию о платформе, производный класс NetworkClient, который использует ваш собственный NetworkConnectionкласс, и, наконец, настроить свой собственный производный класс NetworkLobbyManager для извлечения информации о платформе и ее использования.

//NetworkClient

public class MyNetworkClient: NetworkClient
{
    public MyNetworkClient() : base()
    {
        SetNetworkConnectionClass<MyNetworkConnection>();
    }
}

//NetworkConnection class

public class MyNetworkConnection : NetworkConnection
{
    private RuntimePlatform connectionPlatform;

    public MyNetworkConnection() : base()
    {
        connectionPlatform = Application.platform;
    }

    public RuntimePlatform ConnectionPlatform { get { return connectionPlatform; } }
}

// Suggested adjustment for your NetworkLobbyManagerClass

void AddPlayer(MyNetworkConnection conn)
{
    // I like switches, it's a question of taste imo
    switch(conn.ConnectionPlatform)
    {
        case RuntimePlatform.Android:
            m_currentPlayers.Add(conn.connectionId, 1);
            break;
        case RuntimePlatform.WindowsEditor:
        case RuntimePlatform.WindowsPlayer:
        default:
            m_currentPlayers.Add(conn.connectionId, 0);
    }
}

public override GameObject OnLobbyServerCreateLobbyPlayer(NetworkConnection conn, short playerControllerId)
{
    // Explicitely pass your custom class
    AddPlayer(conn as MyNetworkConnection);
    return base.OnLobbyServerCreateLobbyPlayer(conn, playerControllerId);
}

public override GameObject OnLobbyServerCreateGamePlayer(NetworkConnection conn, short playerControllerId)
{
    GameObject go = Instantiate(spawnPrefabs[m_currentPlayers[conn.connectionId]]);
    NetworkServer.AddPlayerForConnection(conn, go, playerControllerId);

    return go;
}

Я хотел бы услышать от вас, сработало ли это. :)

Отредактировано: поскольку MyNetworkConnection наследуется от NetworkConnection, его можно передать как параметр NetworkConnection. Это означает, что вы можете оставить свои переопределенные методы как есть, однако вам необходимо явно передать свой класс MyNetworkConnection вашему методу AddPlayer.

person Leon Willens    schedule 11.05.2018
comment
Здравствуйте, спасибо за ваше время, но Visual жалуется на метод переопределения OnLobbySerevrCreateLobbyPlayer из-за параметра MyNetworkConnection. А также, что такое base() в MyNetworkClient? - person Kalixio; 11.05.2018
comment
base() относится к конструктору унаследованного класса. Я обновил свой ответ, пожалуйста, просмотрите. - person Leon Willens; 11.05.2018
comment
Я обновил в соответствии с вашими изменениями. В нем говорится, что ссылка на объект не установлена ​​​​на экземпляр объекта LobbyManager.AddPlayer (.MyNetworkConnection conn) (в Assets/Scripts/LobbyManager.cs:42), поскольку он не нашел setNetworkConnectionClass(conn); Я заменил его на SetNetworkConnectionClass‹MyNetworkConnection›(), так что, возможно, это так. - person Kalixio; 11.05.2018
comment
Я также удалил this(), потому что он боролся с ним визуально. - person Kalixio; 11.05.2018
comment
Да, я заметил это. Метод называется SetNetworkConnectionClass(), у меня была опечатка. :( Также вместо this() должно работать base(). - person Leon Willens; 11.05.2018
comment
Поэтому я заменил его на SetNetworkConnectionClass‹MyNetworkConnection›() Это хорошо? - person Kalixio; 11.05.2018
comment
Вы можете сделать это, но вы также должны передать свой пользовательский класс в качестве параметра (как написано выше): SetNetworkConnectionClass<MyNetworkConnection>(conn); - person Leon Willens; 11.05.2018
comment
Да, но SetNetworkConnectionClass(conn); не работает, потому что SetNetworkConnectionClass должен быть чем-то вроде SetNetworkConnectionClass‹T›() - person Kalixio; 11.05.2018
comment
Документация Unity снова в деле :') Тем не менее, это должно работать, так как мой предложенный класс MyNetworkConnection извлекает платформу непосредственно из Application.platform. Вы проверили это? - person Leon Willens; 11.05.2018
comment
Да, но он не может скомпилироваться из-за SetNetworkConnectionClass‹MyNetworkConnection›(conn); Нет перегрузки для аргументов метода SetNetworkConnectionClass' takes 1 - person Kalixio; 11.05.2018
comment
Я снова обновил свой ответ и скорректировал некоторый код на основе ваших выводов. - person Leon Willens; 11.05.2018
comment
Я обновил в соответствии с вашими изменениями. Все компилируется, но здесь происходит сбой: switch (conn.ConnectionPlatform) ullReferenceException: Ссылка на объект не указывает на экземпляр объекта LobbyManager.AddPlayer (.MyNetworkConnection conn) (в Assets/Scripts/LobbyManager.cs:39) - person Kalixio; 11.05.2018
comment
Где вы храните свой метод подключения в качестве клиента? - person Leon Willens; 11.05.2018
comment
Что? У меня просто есть этот компонент с методами, которые вы дали. Извините, я впервые работаю с LobbyManager ^^ - person Kalixio; 11.05.2018
comment
Да, но как ваши игроки подключаются к лобби? - person Leon Willens; 11.05.2018
comment
Они используют графический интерфейс, предоставляемый NetworkManagerGUI, поэтому им просто нужно использовать LAN Host или LAN Client (с IP-адресом), чтобы присоединиться к лобби. - person Kalixio; 11.05.2018
comment
Стандартный NetworkManagerHUD не подойдет для ваших целей, так как он использует стандартный компонент NetworkManager, который, в свою очередь, создает обычный компонент NetworkClient при вызове StartClient(). Обновление моего ответа. - person Leon Willens; 12.05.2018