Страница 1 из 2

M2H Networking Tutorial. Перевод

СообщениеДобавлено: 16 июл 2010, 16:41
Zaicheg
Начал перевод.
Текущий прогресс: все главы, но есть незавершённые участки.
Туториал посвящён организации мультиплеера в 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

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

СообщениеДобавлено: 17 июл 2010, 18:04
Zaicheg
В той или иной степени переведено все разделы. Непереведённые участки выделены красным.

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

СообщениеДобавлено: 20 ноя 2010, 10:18
Robotron18
Перевел мастер сервер на 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;
    }
}
 

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

СообщениеДобавлено: 23 ноя 2010, 22:47
TexeL
На основе данного урока

Multiplayer Tutorial






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

СообщениеДобавлено: 24 ноя 2010, 00:46
Neodrop
(3A4OT)

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

СообщениеДобавлено: 17 янв 2012, 12:48
aradriel
нубский вопрос

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

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

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

кто-нибудь, кто знает, объясните пожалуйста

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

СообщениеДобавлено: 26 янв 2012, 23:20
X-treme
Может уже не актуально, но на всякий случай, берется вот от сюда (когда мы на сам скрипт перетаскиваем(указываем) создаваемый префаб)

Изображение

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

СообщениеДобавлено: 01 фев 2012, 21:35
wwtarasww
Оно расчитано на интернет или только на локальную сетку?

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

СообщениеДобавлено: 04 фев 2012, 14:55
aradriel
Может уже не актуально, но на всякий случай, берется вот от сюда (когда мы на сам скрипт перетаскиваем(указываем) создаваемый префаб)

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

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

на все

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

СообщениеДобавлено: 21 фев 2012, 21:05
Aero7
А нет нигде случайно примера на C#
Чтоб любой пользователь мог зайти и управлять своим кубиком?

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

СообщениеДобавлено: 21 фев 2012, 21:20
Vismar
Aero7 писал(а):А нет нигде случайно примера на C#
Чтоб любой пользователь мог зайти и управлять своим кубиком?

Тут же уже привели уроки(правда на англ),где описано что и как

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

СообщениеДобавлено: 06 мар 2012, 15:12
Ingener
А как сделать чтоб камера по оси Y крутилась?Пробовал MouseLook,запустил 2 примера и получилось что 1 нормально крутится,а на втором вообще перестала камера крутиться.

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

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

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

СообщениеДобавлено: 23 май 2012, 21:15
trololoid
создавать повыше, али уменьшить коллайдер.
У вас один создаётся внутри второго.

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

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

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

Не знаю что делать. Подскажите. Желательно либо уроком либо примером