M2H Networking Tutorial. Перевод

Научился сам? Помоги начинающему.

M2H Networking Tutorial. Перевод

Сообщение Zaicheg 16 июл 2010, 16:41

Начал перевод.
Текущий прогресс: все главы, но есть незавершённые участки.
Туториал посвящён организации мультиплеера в Unity.

Помощь оказали:
ffinder, Noname

Ссылка на тему по оригиналу (там же файлы)
http://forum.unity3d.com/viewtopic.php?t=30788

Ссылки на перевод.
Перевод (формат .docx)
http://docs.unity3d.ru/Tutorials/M2H_Ne ... slate.docx
Перевод (формат .pdf — для тех, у кого проблемы с офисом)
http://docs.unity3d.ru/Tutorials/M2H_Ne ... nslate.pdf
Оригинал
http://docs.unity3d.ru/Tutorials/M2H_Ne ... iginal.pdf
Файлы проекта
http://docs.unity3d.ru/Tutorials/M2H_Ne ... _Files.zip
Дьяченко Роман
e-mail: _zaicheg.reg@gmail.com
skype: zaicheg12
vkontakte: _vk.com/zaichegq
Работа: _wie3.com _www.sanviz.com
Аватара пользователя
Zaicheg
Адепт
 
Сообщения: 3024
Зарегистрирован: 19 июн 2009, 15:12
Откуда: Череповец

Re: M2H Networking Tutorial. Перевод

Сообщение Zaicheg 17 июл 2010, 18:04

В той или иной степени переведено все разделы. Непереведённые участки выделены красным.
Дьяченко Роман
e-mail: _zaicheg.reg@gmail.com
skype: zaicheg12
vkontakte: _vk.com/zaichegq
Работа: _wie3.com _www.sanviz.com
Аватара пользователя
Zaicheg
Адепт
 
Сообщения: 3024
Зарегистрирован: 19 июн 2009, 15:12
Откуда: Череповец

Re: M2H Networking Tutorial. Перевод

Сообщение Robotron18 20 ноя 2010, 10:18

Перевел мастер сервер на C#, массив типизированным списком, неизбежный в джаве мусор подчистил. Работает ощутимо быстрей, но вопросы в надежности остались. Пока детально не потрошил, так что хорошо бы коллективно прошерстить.

mainMenu.cs
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;

public class mainMenu : MonoBehaviour
{
    Rect windowRect1;
    Rect windowRect2;
    Rect windowRect3;

    internal static bool playNowMode = false;
    internal static bool advancedMode = false;
    internal static float playNowModeStarted = 0.0f;

    static string myPlayerName = "MyPlayerName";

    //GUI переменные
    int hostPlayers = 8;
    int hostPort;
    int connectPort;
    string connectIP = "";

    multiplayerScript multiplayerScript;


    void Awake()
    {
        myPlayerName = PlayerPrefs.GetString("playerName");

        multiplayerScript = GetComponent<multiplayerScript>();

        connectPort = hostPort = multiplayerScript.serverPort;
        connectIP = "192.168.0.101";

        windowRect1 = new Rect(Screen.width / 2 - 310, Screen.height / 2 - 90, 380, 280);
        windowRect2 = new Rect(Screen.width / 2 + 85, Screen.height / 2 - 90, 220, 100);
        windowRect3 = new Rect(Screen.width / 2 + 85, Screen.height / 2 + 55, 220, 100);

        playNowMode = false;
        advancedMode = false;
    }


    void OnGUI()
    {
        //If we've connected;  load the game when it's ready to load
        if (Network.isClient || Network.isServer)
        {
            //Since we're connected, load the game
            GUI.Box(new Rect(Screen.width / 4 + 0, Screen.height / 2 - 30, 450, 50), "");
            if (Application.CanStreamedLevelBeLoaded((Application.loadedLevel + 1)))
            {
                GUI.Label(new Rect(Screen.width / 4 + 10, Screen.height / 2 - 25, 285, 150), "Starting the game!");
                Application.LoadLevel((Application.loadedLevel + 1));
            }
            else
            {
                GUI.Label(new Rect(Screen.width / 4 + 10, Screen.height / 2 - 25, 285, 150), "Loading the game: " + Mathf.Floor(Application.GetStreamProgressForLevel((Application.loadedLevel + 1)) * 100) + " %");
            }
            return;
        }

        //Dirty error message popup
        if (multiplayerScript.errorMessage != null && multiplayerScript.errorMessage != "")
        {
            GUI.Box(new Rect(Screen.width / 2 - 100, Screen.height / 2 - 60, 200, 60), "Error");
            GUI.Label(new Rect(Screen.width / 2 - 90, Screen.height / 2 - 50, 180, 50), multiplayerScript.errorMessage);
            if (GUI.Button(new Rect(Screen.width / 2 + 40, Screen.height / 2 - 30, 50, 20), "Close"))
            {
                multiplayerScript.errorMessage = "";
            }
        }

        if (playNowMode)
        {
            playNowFunction();
        }
        else if (advancedMode)
        {
            if (multiplayerScript.errorMessage == null || multiplayerScript.errorMessage == "") //Hide windows on error
            {
                if (GUI.Button(new Rect(455, 90, 140, 30), "Back to main menu"))
                {
                    advancedMode = false;
                }
                windowRect1 = GUILayout.Window(0, windowRect1, listGUI, "Join a game via the list");
                windowRect2 = GUILayout.Window(1, windowRect2, directConnectGUIWindow, "Directly join a game via an IP");
                windowRect3 = GUILayout.Window(2, windowRect3, hostGUI, "Host a game");
            }
        }
        else
        {
            GUI.Box(new Rect(90, 180, 260, 105), "Playername");
            GUI.Label(new Rect(100, 195, 250, 100), "Please enter your name:");

            myPlayerName = GUI.TextField(new Rect(178, 215, 147, 27), myPlayerName);
            if (GUI.changed)
            {
                //Save the name changes
                PlayerPrefs.SetString("playerName", myPlayerName);
            }

            if (myPlayerName == "")
            {
                GUI.Label(new Rect(100, 240, 260, 100), "After entering your name you can start playing!");
                return;
            }

            GUI.Label(new Rect(100, 240, 260, 100), "Click on quickplay to start playing right away!");

            if (GUI.Button(new Rect(400, 150, 150, 30), "Quickplay"))
            {
                playNowMode = true;
                playNowModeStarted = Time.time;
            }
            if (GUI.Button(new Rect(400, 245, 150, 30), "Advanced"))
            {
                advancedMode = true;
            }

        }
    }


    void playNowFunction()
    {
        if (GUI.Button(new Rect(490, 185, 75, 20), "Cancel"))
        {
            Network.Disconnect();
            playNowMode = false;
        }

        GUI.Box(new Rect(Screen.width / 4 + 0, Screen.height / 2 - 50, 420, 50), "");

        if (multiplayerScript.tryingToConnectPlayNowNumber >= 10)
        {
            //If players get fed up waiting they can choose to start a host right away
            if (GUI.Button(new Rect(400, 185, 75, 20), "Just host"))
            {
                multiplayerScript.StartHost(hostPlayers, multiplayerScript.serverPort);
            }
        }

        string connectStatus = multiplayerScript.PlayNow(playNowModeStarted);

        if (connectStatus == "failed")
        {
            //Couldn't find a proper host; host ourselves
            Debug.Log("PlayNow: No games hosted, so hosting one ourselves");
            multiplayerScript.StartHost(7, multiplayerScript.serverPort);
        }
        else
        {
            //Still trying to connect to the first hit
            GUI.Label(new Rect(Screen.width / 4 + 10, Screen.height / 2 - 45, 385, 50), connectStatus);
        }
    }


    void hostGUI(int id)
    {
        GUILayout.BeginVertical();
        GUILayout.Space(10);
        GUILayout.EndVertical();

        GUILayout.BeginHorizontal();
        GUILayout.Space(10);
        GUILayout.Label("Use port: ");
        hostPort = int.Parse(GUILayout.TextField(hostPort.ToString(), GUILayout.MaxWidth(75)));
        GUILayout.Space(10);
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        GUILayout.Space(10);
        GUILayout.Label("Players: ");
        hostPlayers = int.Parse(GUILayout.TextField(hostPlayers.ToString(), GUILayout.MaxWidth(75)));
        GUILayout.Space(10);
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        // Start a new server
        if (GUILayout.Button("Start hosting a server"))
        {
            multiplayerScript.StartHost(hostPlayers, hostPort);
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();
    }


    void directConnectGUIWindow(int id)
    {
        GUILayout.BeginVertical();
        GUILayout.Space(5);
        GUILayout.EndVertical();
        GUILayout.Label(multiplayerScript.connectionInfo);

        if (multiplayerScript.nowConnecting)
        {
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            GUILayout.Label("Trying to connect to " + connectIP + ":" + connectPort);
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
        }
        else
        {
            GUILayout.BeginHorizontal();
            GUILayout.Space(10);
            connectIP = GUILayout.TextField(connectIP, GUILayout.MinWidth(70));
            connectPort = int.Parse(GUILayout.TextField(connectPort + ""));
            GUILayout.Space(10);
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Space(10);
            Network.useNat = GUILayout.Toggle(Network.useNat, "Advanced: Use NAT");
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Space(10);
            GUILayout.FlexibleSpace();

            if (GUILayout.Button("Connect"))
            {
                multiplayerScript.Connect(connectIP, connectPort, Network.useNat);
            }

            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
        }

    }


    private Vector2 scrollPosition;

    void listGUI(int id)
    {
        GUILayout.BeginVertical();
        GUILayout.Space(6);
        GUILayout.EndVertical();

        GUILayout.BeginHorizontal();
        GUILayout.Space(200);

        // Refresh hosts
        if (GUILayout.Button("Refresh available Servers"))
        {
            StartCoroutine(multiplayerScript.FetchHostList(true));
        }
        StartCoroutine(multiplayerScript.FetchHostList(false));

        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        //scrollPosition = GUI.BeginScrollView ( new Rect(0,60,385,200),        scrollPosition, Rect (0, 100, 350, 3000));
        scrollPosition = GUILayout.BeginScrollView(scrollPosition);

        int aHost = 0;

        if (multiplayerScript.sortedHostList != null && multiplayerScript.sortedHostList.Count >= 1)
        {
            foreach (int myElement in multiplayerScript.sortedHostList)
            {
                HostData element = multiplayerScript.hostData[myElement];
                GUILayout.BeginHorizontal();

                // Do not display NAT enabled games if we cannot do NAT punchthrough
                if (!(multiplayerScript.filterNATHosts && element.useNat))
                {
                    aHost = 1;
                    string name = element.gameName + " ";
                    GUILayout.Label(name);
                    GUILayout.FlexibleSpace();
                    GUILayout.Label(element.connectedPlayers + "/" + element.playerLimit);

                    if (element.useNat)
                    {
                        GUILayout.Label(".");
                    }
                    GUILayout.FlexibleSpace();
                    GUILayout.Label("[" + element.ip[0] + ":" + element.port + "]");
                    GUILayout.FlexibleSpace();
                    if (!multiplayerScript.nowConnecting)
                    {
                        if (GUILayout.Button("Connect"))
                        {
                            multiplayerScript.Connect(element.ip, element.port, element.useNat);
                        }
                    }
                    else
                    {
                        GUILayout.Button("Connecting");
                    }
                    GUILayout.Space(15);
                }
                GUILayout.EndHorizontal();
            }
        }
        GUILayout.EndScrollView();
        if (aHost == 0)
        {
            GUILayout.Label("No games hosted at the moment..");
        }
    }
}
 


multiplayerScript.cs
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class multiplayerScript : MonoBehaviour
{
    public string gameName = "Prefix";
    public int serverPort = 25001;

    public HostData[] hostData;

    ConnectionTesterStatus natCapable = ConnectionTesterStatus.Undetermined;
    internal bool filterNATHosts = false;
    bool probingPublicIP = false;
    bool doneTestingNAT = false;
    float timer = 0.0f;

    //bool hideTest = false;
    string testMessage = "Undetermined NAT capabilities";

    private bool tryingToConnectPlayNow = false;
    public int tryingToConnectPlayNowNumber = 0;

    private int[] remotePort = new int[3];
    private string[] remoteIP = new string[3];
    public string connectionInfo = "";

    public bool lastMSConnectionAttemptForcedNat = false;
    //private bool NAToptionWasSwitchedForTesting = false;
    private bool officialNATstatus = Network.useNat;
    public string errorMessage = "";
    private float lastPlayNowConnectionTime;

    public bool nowConnecting = false;

    void Awake()
    {
        // Start connection test
        natCapable = Network.TestConnection();

        // What kind of IP does this machine have? TestConnection also indicates this in the
        // test results
        if (Network.HavePublicAddress())
        {
            Debug.Log("This machine has a public IP address");
        }
        else
        {
            Debug.Log("This machine has a private IP address");
        }
        /* //If you dont want to use the Unity masterserver..
        Network.natFacilitatorIP = myMasterServerIP;
        Network.natFacilitatorPort = 11111;//Change this
        MasterServer.ipAddress = myMasterServerIP;
        MasterServer.port = 22222;//Change this
        Network.connectionTesterIP = myMasterServerIP;
        Network.connectionTesterPort = 33333;//Change this
        */

    }

    IEnumerator Start() //должен быть Start() потому что сопрограмма
    {
        yield return new WaitForSeconds(0.5f);
        int tries = 0;
        while (tries <= 10)
        {
            if (hostData != null && hostData.Length > 0)
            {
                //Waiting for hostData
            }
            else
            {
                StartCoroutine(FetchHostList(true));
            }
            yield return new WaitForSeconds(0.5f);
            tries++;
        }
    }


    void OnFailedToConnectToMasterServer(NetworkConnectionError info)
    {
        //Yikes
    }

    void OnFailedToConnect(NetworkConnectionError info)
    {
        Debug.Log("FailedToConnect info:" + info);
        FailedConnRetry(info);
    }

    internal void Connect(string ip, int port, bool usenat)
    {
        // Enable NAT functionality based on what the hosts if configured to do
        Network.useNat = usenat;
        lastMSConnectionAttemptForcedNat = usenat;

        Debug.Log("Connecting to " + ip + ":" + port + " NAT:" + usenat);
        Network.Connect(ip, port);
        nowConnecting = true;
    }

    //This second definition of Connect can handle the ip string[] passed by the masterserver
    internal void Connect(string[] ip, int port, bool usenat)
    {
        // Enable NAT functionality based on what the hosts if configured to do
        Network.useNat = usenat;
        lastMSConnectionAttemptForcedNat = usenat;

        Debug.Log("Connecting to " + ip[0] + ":" + port + " NAT:" + usenat);
        Network.Connect(ip, port);
        nowConnecting = true;
    }

    internal void StartHost(int players, int port)
    {
        if (players <= 1)
        {
            players = 1;
        }
        //Network.InitializeSecurity();
        Network.InitializeServer(players, port);
    }

    void OnConnectedToServer()
    {
        //Stop communication until in the game
        Network.isMessageQueueRunning = false;

        //Save these details so we can use it in the next scene
        PlayerPrefs.SetString("connectIP", Network.connections[0].ipAddress);
        PlayerPrefs.SetInt("connectPort", Network.connections[0].port);
    }

    void FailedConnRetry(NetworkConnectionError info)
    {
        bool mayRetry = true;
        if (info == NetworkConnectionError.InvalidPassword)
        {
            mayRetry = false;
        }

        nowConnecting = false;

        //Quickplay
        if (tryingToConnectPlayNow)
        {
            //Try again without NAT if we used NAT
            if (mayRetry && Network.useNat && lastMSConnectionAttemptForcedNat)
            {
                Debug.Log("Failed connect 1A: retry without NAT");

                remotePort[0] = serverPort;//Fall back to default server port
                Connect(remoteIP, remotePort[0], false);
                lastPlayNowConnectionTime = Time.time;
            }
            else
            {
                //We didn't use NAT and failed
                Debug.Log("Failed connect 1B: Don't retry");

                //Reset NAT to org. value
                Network.useNat = officialNATstatus;

                //Connect to next playnow/quickplay host
                tryingToConnectPlayNowNumber++;
                tryingToConnectPlayNow = false;
            }
        }
        else
        {
            //Direct connect or via host list manually
            connectionInfo = "Failed to connect!";

            if (mayRetry && Network.useNat && lastMSConnectionAttemptForcedNat)
            {
                //Since the last connect forced NAT usage,
                // let's try again without NAT.        
                Network.useNat = false;
                Network.Connect(remoteIP, remotePort[0]);
                nowConnecting = true;
                lastPlayNowConnectionTime = Time.time;
            }
            else
            {
                Debug.Log("Failed 2b");

                if (info == NetworkConnectionError.InvalidPassword)
                {
                    errorMessage = "Failed to connect: Wrong password supplied";
                }
                else if (info == NetworkConnectionError.TooManyConnectedPlayers)
                {
                    errorMessage = "Failed to connect: Server is full";
                }
                else
                {
                    errorMessage = "Failed to connect";
                }

                //reset to default port
                remotePort[0] = serverPort;

                //Reset nat to tested value
                Network.useNat = officialNATstatus;
            }
        }
    }

    public float CONNECT_TIMEOUT = 0.75f;
    public float CONNECT_NAT_TIMEOUT = 5.00f;

    //Our quickplay function: Go trough the gameslist and try to connect to all games
    internal string PlayNow(float timeStarted)
    {
        int i = 0;

        foreach (int myElement in sortedHostList)
        {
            HostData element = hostData[myElement];

            // Do not try NAT enabled games if we cannot do NAT punchthrough
            // Do not try connecting to password protected games
            if (!(filterNATHosts && element.useNat) && !element.passwordProtected)
            {
                //int aHost = 1;

                if (element.connectedPlayers < element.playerLimit)
                {
                    if (tryingToConnectPlayNow)
                    {
                        string natText;
                        if (Network.useNat)
                        {
                            natText = " with option 1/2";
                        }
                        else
                        {
                            natText = " with option 2/2";
                        }
                        if ((!Network.useNat && lastPlayNowConnectionTime + CONNECT_TIMEOUT <= Time.time) || (Network.useNat && lastPlayNowConnectionTime + CONNECT_NAT_TIMEOUT <= Time.time))
                        {
                            Debug.Log("Interrupted by timer, NAT:" + Network.useNat);
                            FailedConnRetry(NetworkConnectionError.ConnectionFailed);
                        }
                        return "Trying to connect to host " + (tryingToConnectPlayNowNumber + 1) + "/" + sortedHostList.Count + " " + natText;
                    }
                    if (!tryingToConnectPlayNow && tryingToConnectPlayNowNumber <= i)
                    {
                        Debug.Log("Trying to connect to game NR " + i + " & " + tryingToConnectPlayNowNumber);
                        tryingToConnectPlayNow = true;
                        tryingToConnectPlayNowNumber = i;

                        // Enable NAT functionality based on what the hosts if configured to do
                        lastMSConnectionAttemptForcedNat = element.useNat;
                        Network.useNat = element.useNat;
                        int connectPort = element.port;
                        if (Network.useNat)
                        {
                            print("Using Nat punchthrough to connect");
                        }
                        else
                        {
                            //connectPort=serverPort; //bad idea!
                            print("Connecting directly to host");
                        }
                        Debug.Log("connecting to " + element.gameName + " " + element.ip + ":" + connectPort);
                        Network.Connect(element.ip, connectPort);
                        lastPlayNowConnectionTime = Time.time;
                    }
                    i++;
                }
            }
        }

        //If we reach this point then either we've parsed the whole list OR the list is still empty

        //Dont give up yet: Give MS 7 seconds to feed the list
        if (Time.time < timeStarted + 7)
        {
            StartCoroutine(FetchHostList(true));
            return "Waiting for masterserver..." + Mathf.Ceil((timeStarted + 7) - Time.time);
        }

        if (!tryingToConnectPlayNow)
        {
            return "failed";
        }
        else
        {
            return "Ok!!!";
        }
    }


    void Update()
    {
        // If network test is undetermined, keep running
        if (!doneTestingNAT)
        {
            TestConnection();
        }
    }

    void TestConnection()
    {
        // Start/Poll the connection test, report the results in a label and react to the results accordingly
        natCapable = Network.TestConnection();
        switch (natCapable)
        {
            case ConnectionTesterStatus.Error:
                testMessage = "Problem determining NAT capabilities";
                doneTestingNAT = true;
                break;

            case ConnectionTesterStatus.Undetermined:
                testMessage = "Undetermined NAT capabilities";
                doneTestingNAT = false;
                break;

            case ConnectionTesterStatus.PrivateIPNoNATPunchthrough:
                testMessage = "Cannot do NAT punchthrough, filtering NAT enabled hosts for client connections, local LAN games only.";
                filterNATHosts = true;
                Network.useNat = true;
                doneTestingNAT = true;
                break;

            case ConnectionTesterStatus.PrivateIPHasNATPunchThrough:
                if (probingPublicIP)
                    testMessage = "Non-connectable public IP address (port " + serverPort + " blocked), NAT punchthrough can circumvent the firewall.";
                else
                    testMessage = "NAT punchthrough capable. Enabling NAT punchthrough functionality.";
                // NAT functionality is enabled in case a server is started,
                // clients should enable this based on if the host requires it
                Network.useNat = true;
                doneTestingNAT = true;
                break;

            case ConnectionTesterStatus.PublicIPIsConnectable:
                testMessage = "Directly connectable public IP address.";
                Network.useNat = false;
                doneTestingNAT = true;
                break;

            // This case is a bit special as we now need to check if we can
            // cicrumvent the blocking by using NAT punchthrough
            case ConnectionTesterStatus.PublicIPPortBlocked:
                testMessage = "Non-connectble public IP address (port " + serverPort + " blocked), running a server is impossible.";
                Network.useNat = false;
                // If no NAT punchthrough test has been performed on this public IP, force a test
                if (!probingPublicIP)
                {
                    Debug.Log("Testing if firewall can be circumnvented");
                    natCapable = Network.TestConnectionNAT();
                    probingPublicIP = true;
                    timer = Time.time + 10;
                }
                // NAT punchthrough test was performed but we still get blocked
                else if (Time.time > timer)
                {
                    probingPublicIP = false;            // reset
                    Network.useNat = true;
                    doneTestingNAT = true;
                }
                break;
            case ConnectionTesterStatus.PublicIPNoServerStarted:
                testMessage = "Public IP address but server not initialized, it must be started to check server accessibility. Restart connection test when ready.";
                break;
            default:
                testMessage = "Error in test routine, got " + natCapable;
                break;
        }
        officialNATstatus = Network.useNat;
        if (doneTestingNAT)
        {
            Debug.Log("TestConn:" + testMessage);
            Debug.Log("TestConn:" + natCapable + " " + probingPublicIP + " " + doneTestingNAT);
        }
    }

    private float lastHostListRequest = 0;

    //Request the host limit, but we limit these requests
    //Max once every two minutes automatically, max once every 5 seconds when manually requested
    internal IEnumerator FetchHostList(bool manual)
    {
        int timeout = 120;
        if (manual)
        {
            timeout = 5;
        }

        if (lastHostListRequest == 0 || Time.realtimeSinceStartup > lastHostListRequest + timeout)
        {
            lastHostListRequest = Time.realtimeSinceStartup;
            MasterServer.RequestHostList(gameName);
            yield return new WaitForSeconds(1);//We gotta wait :/                      
            hostData = MasterServer.PollHostList();
            yield return new WaitForSeconds(1);//We gotta wait :/      
            CreateSortedArray();
            Debug.Log("Requested new host list, got: " + hostData.Length);
        }
    }

   
    //The code below is all about sorting the game list by playeramount
    internal List<int> sortedHostList;

    void CreateSortedArray()
    {
        sortedHostList = new List<int>();

        HostData[] data = hostData;
        for (int i = 0; i < data.Length; i++)
        {
            AddToArray(i);
            i++;
        }
    }

    void AddToArray(int nr)
    {
        sortedHostList.Add(nr);
        SortLastItem();
    }

    void SortLastItem()
    {
        if (sortedHostList.Count <= 1)
            return;

        for (int i = sortedHostList.Count - 1; i > 0; i--)
        {
            int value1 = hostData[sortedHostList[i - 1]].connectedPlayers;
            int value2 = hostData[sortedHostList[i]].connectedPlayers;
            if (value1 < value2)
            {
                SwapArrayItem((i - 1), i);
            }
            else
            {//Sorted!
                return;
            }
        }
    }

    void SwapArrayItem(int nr1, int nr2)
    {
        int tmp = sortedHostList[nr1];
        sortedHostList[nr1] = sortedHostList[nr2];
        sortedHostList[nr2] = tmp;
    }
}
 
Robotron18
UNец
 
Сообщения: 40
Зарегистрирован: 25 июл 2010, 15:48

Re: M2H Networking Tutorial. Перевод

Сообщение TexeL 23 ноя 2010, 22:47

На основе данного урока

Multiplayer Tutorial





Аватара пользователя
TexeL
UNITрон
 
Сообщения: 244
Зарегистрирован: 15 ноя 2009, 20:57
  • Сайт

Re: M2H Networking Tutorial. Перевод

Сообщение Neodrop 24 ноя 2010, 00:46

(3A4OT)
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: M2H Networking Tutorial. Перевод

Сообщение aradriel 17 янв 2012, 12:48

нубский вопрос

в туториале 2B, там где происходит инстансирование игрового объекта (куба) мне совсем не понятно, каким образом вообще прописывается, что именно этот куб со скриптами должен быть инстансирован?

в скрипте Spawnscript указывается просто некая переменная playerPrefab, а по факту добавляется на сцену именно этот куб, заготовленный заранее.

если бы в скрипте указано было его имя, я бы понял, а так - не понятно

кто-нибудь, кто знает, объясните пожалуйста
Аватара пользователя
aradriel
UNIт
 
Сообщения: 68
Зарегистрирован: 13 янв 2012, 07:05
Откуда: Екатеринбург

Re: M2H Networking Tutorial. Перевод

Сообщение X-treme 26 янв 2012, 23:20

Может уже не актуально, но на всякий случай, берется вот от сюда (когда мы на сам скрипт перетаскиваем(указываем) создаваемый префаб)

Изображение
X-treme
UNец
 
Сообщения: 3
Зарегистрирован: 21 янв 2012, 17:19

Re: M2H Networking Tutorial. Перевод

Сообщение wwtarasww 01 фев 2012, 21:35

Оно расчитано на интернет или только на локальную сетку?
ИзображениеИзображениеИзображениеИзображение
wwtarasww
UNIт
 
Сообщения: 135
Зарегистрирован: 28 фев 2011, 21:19
Откуда: Ukraine

Re: M2H Networking Tutorial. Перевод

Сообщение aradriel 04 фев 2012, 14:55

Может уже не актуально, но на всякий случай, берется вот от сюда (когда мы на сам скрипт перетаскиваем(указываем) создаваемый префаб)

спасибо =) дейсвтительно еще актуально

Оно расчитано на интернет или только на локальную сетку?

на все
Аватара пользователя
aradriel
UNIт
 
Сообщения: 68
Зарегистрирован: 13 янв 2012, 07:05
Откуда: Екатеринбург

Re: M2H Networking Tutorial. Перевод

Сообщение Aero7 21 фев 2012, 21:05

А нет нигде случайно примера на C#
Чтоб любой пользователь мог зайти и управлять своим кубиком?
Aero7
UNIт
 
Сообщения: 82
Зарегистрирован: 17 окт 2011, 19:04

Re: M2H Networking Tutorial. Перевод

Сообщение Vismar 21 фев 2012, 21:20

Aero7 писал(а):А нет нигде случайно примера на C#
Чтоб любой пользователь мог зайти и управлять своим кубиком?

Тут же уже привели уроки(правда на англ),где описано что и как
Аватара пользователя
Vismar
UNIт
 
Сообщения: 107
Зарегистрирован: 21 янв 2012, 11:20

Re: M2H Networking Tutorial. Перевод

Сообщение Ingener 06 мар 2012, 15:12

А как сделать чтоб камера по оси Y крутилась?Пробовал MouseLook,запустил 2 примера и получилось что 1 нормально крутится,а на втором вообще перестала камера крутиться.
Ingener
UNIт
 
Сообщения: 53
Зарегистрирован: 06 мар 2012, 14:50

Re: M2H Networking Tutorial. Перевод

Сообщение OdIUm 23 май 2012, 20:26

Сделал с шариком - все ок. Сделал вместо шарика - First Person Controller, добавил к нему PlayerControl скрипт (из туториала), ригбоди и нетворк вью, при спавне игрок сквозь землю проваливается и падает. Земля - растянутый куб.
Кто знает почему?
Пробовал дефолтные скины отрубать, что на контроллере - не помогает(
OdIUm
UNец
 
Сообщения: 46
Зарегистрирован: 18 май 2012, 22:57

Re: M2H Networking Tutorial. Перевод

Сообщение trololoid 23 май 2012, 21:15

создавать повыше, али уменьшить коллайдер.
У вас один создаётся внутри второго.
Аватара пользователя
trololoid
Старожил
 
Сообщения: 712
Зарегистрирован: 15 сен 2011, 19:18
Откуда: Туапсе, Краснодарский край, Россия

Re: M2H Networking Tutorial. Перевод

Сообщение OdIUm 23 май 2012, 21:36

Не совсем понял что сделать надо...
У меня проблема в следующем. Если сделать контроллер от первого лица (стандартный), то при появлении 2го персонажа - каждый из них управляется равномерно и оба игрока управляют ими... Тоесть один двинулся - второй тоже.
С шариками так не происходит.

Не знаю в чем причина. Решил просто на контроллер стандартный нацепить контроллер из шарика, но теперь он просто сквозь землю проваливается.

Не знаю что делать. Подскажите. Желательно либо уроком либо примером
OdIUm
UNец
 
Сообщения: 46
Зарегистрирован: 18 май 2012, 22:57

След.

Вернуться в Уроки

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2