Показать сообщение отдельно
Старый 27.07.2010, 12:06   #1
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Unity3d - сеть (M2H_2B)

Как ясно из названия - я собираюсь показать работу с сетью на основе примера (M2H_2.
Я перевел три скрипта, необходимых для сборки сетевого приложения, на C# и следовательно тема в нужном разделе.

Итак:

1. Скрипт подключения к сети "Connect.cs":
using UnityEngine;
using System.Collections;

public class 
Connect MonoBehaviour
{

    public 
string connectToIP "127.0.0.1";
    public 
int connectPort 25001;

    
// Смешанный GUI для сервера и клиента
    
public void OnGUI()
    {

        if (
Network.peerType == NetworkPeerType.Disconnected)
        {
            
//Сейчас мы отключены и не являемся клиентом или хостом
            
GUILayout.Label("Connection status: Disconnected");

            
connectToIP GUILayout.TextField(connectToIPGUILayout.MinWidth(100));
            
connectPort int.Parse(GUILayout.TextField(connectPort.ToString()));

            
GUILayout.BeginVertical();
            if (
GUILayout.Button("Connect as client"))
            {
                
// Подсоединяемся к "connectToIP" и "connectPort" как клиент
                // В данном случае игнорируем NAT
                
Network.useNat false;
                
Network.Connect(connectToIPconnectPort);
            }

            if (
GUILayout.Button("Start Server"))
            {
                
// Создаем север с 32 клиентами используя порт "connectPort" 
                // Так же игнорируем NAT
                
Network.useNat false;
                
Network.InitializeServer(32connectPort);
            }
            
GUILayout.EndVertical();


        }
        else
        {
            
//Мы имеем подключение(я)!


            
if (Network.peerType == NetworkPeerType.Connecting)
            {
                
// Статус - пдключение
                
GUILayout.Label("Connection status: Connecting");

            }
            else if (
Network.peerType == NetworkPeerType.Client)
            {
                
// Статус - клиент
                
GUILayout.Label("Connection status: Client!");
                
GUILayout.Label("Ping to server: " Network.GetAveragePing(Network.connections[0]));

            }
            else if (
Network.peerType == NetworkPeerType.Server)
            {
                
// Статус - сервер
                
GUILayout.Label("Connection status: Server!");
                
GUILayout.Label("Connections: " Network.connections.Length);
                if (
Network.connections.Length >= 1)
                {
                    
GUILayout.Label("Ping to first player: " Network.GetAveragePing(Network.connections[0]));
                }
            }

            if (
GUILayout.Button("Disconnect"))
            {
                
Network.Disconnect(200);
            }
        }


    }

    
// ВСЕ функции ниже НЕ ИСПОЛЗУЮТСЯ в данном примере, а приведены только для демонстрации.
    // Сначала убедитесь в понимании кода, приведенного выше в функции OnGUI()

    // Слиентские фукнции, вызываемые Юнити
    
public void OnConnectedToServer()
    {
        
// Этот КЛИЕНТ подключился к серверу
        
Debug.Log("This CLIENT has connected to a server");
    }

    public 
void OnDisconnectedFromServer(NetworkDisconnection info)
    {
        
// Этот СЕРВЕР или КЛИЕНТ отключился от сервера
        
Debug.Log("This SERVER OR CLIENT has disconnected from a server");
    }

    public 
void OnFailedToConnect(NetworkConnectionError error)
    {
        
// Не удалось поключиться к серверу
        
Debug.Log("Could not connect to server: " error);
    }


    
//Серверные фукнции, вызываемые Юнити
    
public void OnPlayerConnected(NetworkPlayer player)
    {
        
Debug.Log("Player connected from: " player.ipAddress ":" player.port);
    }

    public 
void OnServerInitialized()
    {
        
// Сервер инициализирован и готов
        
Debug.Log("Server initialized and ready");
    }

    public 
void OnPlayerDisconnected(NetworkPlayer player)
    {
        
// Игрок отсоединился от player.ipAddress + ":" + player.port
        
Debug.Log("Player disconnected from: " player.ipAddress ":" player.port);
    }


    
// OTHERS:
    // Для полного обзора всех сетевых функций вызываемых Юнити
    // следующие четыре так же были добавлены, но они сейчас игнорируются

    
public void OnFailedToConnectToMasterServer(NetworkConnectionError info)
    {
        
// Не удалось соединиться с мастер-сервером
        
Debug.Log("Could not connect to master server: " info);
    }

    public 
void OnNetworkInstantiate(NetworkMessageInfo info)
    {
        
// Новый объект был создан info.sender
        
Debug.Log("New object instantiated by " info.sender);
    }

    public 
void OnSerializeNetworkView(BitStream streamNetworkMessageInfo info)
    {
        
//Пользовательский код здесь (Ваш код!)
    
}


2. Скрипт игрока "PlayerScript.cs":
using UnityEngine;

[
RequireComponent(typeof(NetworkView))]
public class 
PlayerScript MonoBehaviour
{
    public 
void Awake()
    {
        if (!
networkView.isMine)
        {
            
// Если не мы владельцы данного объекта, то выключаем данный скрипт.
            // Но помним, что RPC и OnSerializeNetworkView работают в любом случае
            
enabled false;
        }
    }

    public 
void Update()
    {

        if (
networkView.isMine)
        {
            
// Только владелец может двигать куб!            
            
Vector3 moveDirection = new Vector3(
                
Input.GetAxis("Horizontal"), 0Input.GetAxis("Vertical"));
            
float speed 5;
            
transform.Translate(speed moveDirection Time.deltaTime);
        }

    }


    public 
void OnSerializeNetworkView(BitStream streamNetworkMessageInfo info)
    {
        if (
stream.isWriting)
        {
            
// Выполняется у владельца networkview; 
            // Сервер рассылает позицию по сети

            
Vector3 pos transform.position;
            
stream.Serialize(ref pos);//"Кодирование" и рассылка

        
}
        else
        {
            
// Выполняется у всех остальных; 
            // Клиенты получают позицию и устанавливают ее

            
Vector3 posReceive Vector3.zero;
            
stream.Serialize(ref posReceive); //"Декодирование" и прием
            
transform.position posReceive;

        }
    }


3. Скрипт создающий игроков при подключении и удалящий при отключении "SpawnScript.cs":
using UnityEngine;
using System.Collections;

public class 
SpawnScript MonoBehaviour
{
    public 
Transform playerPrefab;


    public 
void OnServerInitialized()
    {
        
Spawnplayer();
    }

    public 
void OnConnectedToServer()
    {
        
Spawnplayer();
    }

    public 
void Spawnplayer()
    {

        
Transform myNewTrans = (Transform)Network.Instantiate(
            
playerPrefabtransform.positiontransform.rotation0);

    }

    public 
void OnPlayerDisconnected(NetworkPlayer player)
    {
        
// Чистим за игроком
        
Debug.Log("Clean up after player " player);
        
Network.RemoveRPCs(player);
        
Network.DestroyPlayerObjects(player);
    }

    public 
void OnDisconnectedFromServer(NetworkDisconnection info)
    {
        
// При отключении от сервера чистим за собой
        
Debug.Log("Clean up a bit after server quit");
        
Network.RemoveRPCs(Network.player);
        
Network.DestroyPlayerObjects(Network.player);

        
/* 
         * Запомните, что мы удаляем только наши объекты и не можем удалить объекты других игроков
         * т.к. мы не знаем где они и мы не следим за ними.
         * В игре обычно вы должны перезагрузить уровень или загрузить уровень с главным меню ;).
         * Сейчас мы можем использовать здесь "Application.LoadLevel(Application.loadedLevel);" для сброса сцены.
         */
        
Application.LoadLevel(Application.loadedLevel);
    }

Я надеюсь функциональность данных скриптов вы поняли прочитав переведенные мной комментарии.

Сборка сцены:
  1. Создаем в сцене пустой GameObject и называем его Connect. Вешаем на него скрипт "Connet.cs". Данный объект будет отображать GUI для подсоединения к сети или создании сервера.
  2. Создаем в сцене пустой GameObject и называем его SpawnScript. Вешаем на него скрипт "SpawnScript.cs". Данный объект будет создавать и удалять данные игроков.
  3. Создаем префаб игрока. Для Этого создаем кубик. На него вешаем "PlayerScript.cs" который автоматически ему добавляет компонент "NetworkView". Перетаскиваем скрипт PlayerScript назначенный кубику на поле Observed компонента NetworkView и устанавливаем параметр State Synchronization в Reliable Data Compressed. Создаем в проекте пустой префаб и перетаскиваем туда наш кубик.
  4. Назначаем наш созданный префаб игрока в SpawnScript полю Player Prefab (он должен знать как создать игрока).
Вроде все готово, можно собирать и тестировать. Чтобы тестировать на своей машине, нужно указать юнити, что следует работать в фоновом режиме: Edit->Project Settings->Player->Run In Background

Данный пример демонстрирует работу сети где сервер НЕ рулит

Заметки: камера сейчас одна и будет у каждого игрока в том месте, где она установлена с самого начала. Я думаю (не проверял), что для этого в скрипте PlayerScript в методе Awake, если созданный игрок принадлежит текущему сетевому игроку, нужно ее создать и привязать к этому префабу.

PS: вообще я не собирал эту сцену, я только перевел скрипты на C# и написал порядок сборки но должно работать)
__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием
Эти 10 пользователя(ей) сказали Спасибо pax за это полезное сообщение:
CPAHb (18.07.2013), den (27.07.2010), Dream (27.07.2010), Evgen (15.04.2016), Fatalix3d (27.07.2010), Illidan (27.07.2010), Ingener (02.02.2012), maxturbo (28.03.2011), Nerd (05.02.2012), Nuprahtor (21.04.2013)