2017-09-18 4 views
1

Unity의 NetworkTransport를 구현하는 방법에 대한 광범위한 자습서를 읽었습니다. 내가 따라 다니는 동안 모두 의미가 있었지만 완료하고 변경하기 시작했습니다. 나를. 서버와 클라이언트 스크립트간에 모든 것이 어떻게 관련되는지, 서버/클라이언트에 보낼 추가 변수를 추가하는 방법을 이해하려면 약간의 도움이 필요합니다.NetworkTransport : 서버 및 클라이언트에 여러 데이터 보내기

현재 스크립트가있는 곳에서 클라이언트 측에 두 개의 추가 변수 (Texture2D 및 문자열)를 추가하여 플레이어 클래스에 추가하고 서버 및 다른 클라이언트에 전달합니다.

이 두 가지 추가 변수를 Player 클래스에 추가하고 서버 스크립트의 내 ServerClient 클래스에도 동일한 변수를 추가하여 클라이언트 스크립트에서 시작했습니다. 그런 다음 SpawnPlayer 함수의 클라이언트 스크립트에서이 두 가지 추가 변수를 전달하지만 처음 두 변수를 저장하는 올바른 문자열을 어떻게 생성하는지 혼란스러워합니다. 누구든지 올바른 방향으로 나를 가리킬 수 있다면 엄청난 도움이 될 것입니다. 고맙습니다!

'NetworkServerController.cs'

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

public class ServerClient 
{ 
    public int connectionID; 
    public string playerName; 
    public Texture2D animalTex; 
    public string animalType; 
    public Vector3 position; 
} 

public class NetworkServerController : MonoBehaviour { 

    private const int MAX_CONNECTION = 10; 
    private int port = 5701; 

    private int hostID; 
    private int webHostID; 

    private string networkConnections; 

    private int reliableChannel; 
    private int unreliableChannel; 
    private int reliableFragChannel; 
    private int unreliableFragChannel; 

    private bool isStarted = false; 
    private byte error; 

    private List<ServerClient> clients = new List<ServerClient>(); 

    private float lastMovementUpdate; 
    private float movementUpdateRate = 0.2f; 

    // Onscreen Variables 
    private string connectText; 
    private string dataText; 
    private string clientID; 

    private void Awake() 
    { 
     NetworkServer.Reset(); 
    } 

    private void Start() 
    { 
     NetworkTransport.Init(); 
     ConnectionConfig cc = new ConnectionConfig(); 

     reliableChannel = cc.AddChannel(QosType.Reliable); 
     unreliableChannel = cc.AddChannel(QosType.Unreliable); 
     reliableFragChannel = cc.AddChannel(QosType.ReliableFragmented); 
     unreliableFragChannel = cc.AddChannel(QosType.UnreliableFragmented); 

     HostTopology topo = new HostTopology(cc, MAX_CONNECTION); 

     hostID = NetworkTransport.AddHost(topo, port); 
     Debug.Log("Socket Open. HostID is : " + hostID); 

     webHostID = NetworkTransport.AddWebsocketHost(topo, port); 
     Debug.Log("Socket Open. webHostID is : " + webHostID); 

     isStarted = true; 
    } 

    int connectionId; 

    private void Update() 
    { 
     if (!isStarted) 
     { 
      return; 
     } 
     else if (isStarted) 
     { 
      // Debug.Log("Server Started."); 

      int recHostId; 
      int channelId; 
      byte[] recBuffer = new byte[1024]; 
      int bufferSize = 1024; 
      int dataSize; 
      byte error; 
      NetworkEventType recData = NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error); 

      // Network Messenger System 
      switch (recData) 
      { 
       case NetworkEventType.ConnectEvent: //2 
        Debug.Log("Player " + connectionId + "has connected."); 
        OnConnection(connectionId); 
        break; 

       case NetworkEventType.DataEvent:  //3 
        string msg = Encoding.Unicode.GetString(recBuffer, 0, dataSize); 
        Debug.Log("Receiving from " + connectionId + " : " + msg); 
        string[] splitData = msg.Split('|'); 

        switch (splitData[0]) 
        { 
         case "NAMEIS": 
          OnNameIs(connectionId, splitData[1]); 
          break; 

         case "MYPOSITION": 
          OnMyPosition(connectionId, float.Parse(splitData[1]), float.Parse(splitData[2])); 
          break; 

         default: 
          Debug.Log("Invalid message : " + msg); 
          break; 
        } 

        break; 

       case NetworkEventType.DisconnectEvent: //4 
        Debug.Log("Player " + connectionId + "has disconnected."); 
        OnDisconnection(connectionId); 
        break; 
      } 

      // Ask player for their position 
      if (Time.time - lastMovementUpdate > movementUpdateRate) 
      { 
       lastMovementUpdate = Time.time; 
       string m = "ASKPOSITION|"; 
       foreach (ServerClient sc in clients) 
        m += sc.connectionID.ToString() + '%' + sc.position.x.ToString() + '%' + sc.position.y.ToString() + '|'; 
       m = m.Trim('|'); 

       Send(m, unreliableChannel, clients); 
      } 
     }  
    } 

    private void OnConnection(int cnnID) 
    { 
     // Add player to list 
     ServerClient c = new ServerClient(); 
     c.connectionID = cnnID; 
     c.playerName = "TEMP"; 
     clients.Add(c); 

     // When player joins server, tell ID 
     // Request player name and send name of all the other players 
     string msg = "ASKNAME|" + cnnID + "|"; 
     foreach (ServerClient sc in clients) 
      msg += sc.playerName + '%' + sc.connectionID + "|"; 

     msg = msg.Trim('|'); 

     // ASKNAME|3|DAVE%1|MIKE%2|TEMP%3 

     Send(msg, reliableChannel, cnnID); 
    } 

    private void OnDisconnection(int cnnId) 
    { 
     // Remove this player from our client list 
     clients.Remove(clients.Find(x => x.connectionID == cnnId)); 

     // Tell everyone that someone has disconnected 
     Send("DC|" + cnnId, reliableChannel, clients); 
    } 

    private void OnNameIs(int cnnID, string playerName) 
    { 
     // Link name to connection ID 
     clients.Find(x => x.connectionID == cnnID).playerName = playerName; 

     // Tell everone that a new player has connected 
     Send("CNN|" + playerName + '|' + cnnID, reliableChannel, clients); 
    } 

    private void OnMyPosition(int cnnId, float x, float y) 
    { 
     clients.Find(c => c.connectionID == cnnId).position = new Vector3(x, y, 0); 
    } 

    private void Send(string message, int channelID, int cnnID) 
    { 
     List<ServerClient> c = new List<ServerClient>(); 
     c.Add(clients.Find(x => x.connectionID == cnnID)); 
     Send(message, channelID, c); 
    } 

    // overload method 
    private void Send(string message, int channelID, List<ServerClient> c) 
    { 
     Debug.Log("Sending : " + message); 
     byte[] msg = Encoding.Unicode.GetBytes(message); 
     foreach(ServerClient sc in c) 
     { 
      NetworkTransport.Send(hostID, sc.connectionID, channelID, msg, message.Length * sizeof(char), out error); 
     } 
    } 
} 

'NetworkClientController'.cs

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

public class Player 
{ 
    public string playerName; 
    public GameObject avatar; 
    public int connectionId; 
    public Texture2D animalTex; 
    public string animalType; 
} 

public class NetworkClientController : MonoBehaviour { 

    private const int MAX_CONNECTION = 10; 
    private int port = 5701; 
    private string IPAddress = "192.168.1.160"; 

    private int hostID; 
    private int webHostID; 

    private int reliableChannel; 
    private int unreliableChannel; 
    private int reliableFragChannel; 
    private int unreliableFragChannel; 

    private int ourClientID; 
    private int connectionID; 

    private float connectionTime; 
    private bool isConnected = false; 
    private bool isStarted = false; 
    private byte error; 

    private string playerName; 

    public GameObject playerPrefab; 
    public Dictionary<int, Player> players = new Dictionary<int, Player>(); 

    private void Start() 
    { 
     // Connect(); 
    } 

    public void Connect() 
    { 
     // Check player name 
     string pName = GameObject.Find("NameInput").GetComponent<InputField>().text; 

     if (pName == "") 
     { 
      Debug.Log("You must enter a name"); 
      return; 
     } 

     playerName = pName; 

     NetworkTransport.Init(); 
     ConnectionConfig cc = new ConnectionConfig(); 

     reliableChannel = cc.AddChannel(QosType.Reliable); 
     unreliableChannel = cc.AddChannel(QosType.Unreliable); 
     reliableFragChannel = cc.AddChannel(QosType.ReliableFragmented); 
     unreliableFragChannel = cc.AddChannel(QosType.UnreliableFragmented); 

     HostTopology topo = new HostTopology(cc, MAX_CONNECTION); 

     hostID = NetworkTransport.AddHost(topo, port); 
     connectionID = NetworkTransport.Connect(hostID, IPAddress, port, 0, out error); 

     connectionTime = Time.time; 
     isConnected = true; 
    } 

    private void Update() 
    { 
     if (!isConnected) 
      return; 

     int recHostId; 
     int connectionId; 
     int channelId; 
     byte[] recBuffer = new byte[1024]; 
     int bufferSize = 1024; 
     int dataSize; 
     byte error; 
     NetworkEventType recData = NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error); 

     // Network Messenger System 
     switch (recData) 
     { 
      case NetworkEventType.DataEvent:  //3 
       string msg = Encoding.Unicode.GetString(recBuffer, 0, dataSize); 
       Debug.Log("Receiving " + msg); 
       string[] splitData = msg.Split('|'); 

       switch (splitData[0]) 
       { 
        case "ASKNAME": 
         OnAskName(splitData); 
         break; 

        case "ASKPOSITION": 
         OnAskPosition(splitData); 
         break; 

        case "CNN": 
         SpawnPlayer(splitData[1], int.Parse(splitData[2])); 
         break; 

        case "DC": 
         PlayerDisconnected(int.Parse(splitData[1])); 
         break; 

        default: 
         Debug.Log("Invalid message : " + msg); 
         break; 
       } 
       break; 
     } 
    } 

    private void OnAskName(string[] data) 
    { 
     // Set local client ID 
     ourClientID = int.Parse(data[1]); 

     // Send local client name to the server 
     Send("NAMEIS|" + playerName, reliableChannel); 

     // Create all remote client players 
     for(int i = 2; i < data.Length - 1; i++) 
     { 
      string[] d = data[i].Split('%'); 
      SpawnPlayer(d[0], int.Parse(d[1])); 
     } 
    } 

    private void OnAskPosition(string[] data) 
    { 
     if (!isStarted) 
      return; 

     // Update remote client positions 
     for (int i = 1; i < data.Length - 1; i++) 
     { 
      string[] d = data[i].Split('%'); 

      // Prevent the server from updating local client 
      if (ourClientID != int.Parse(d[0])) 
      { 
       Vector3 position = Vector3.zero; 
       position.x = float.Parse(d[1]); 
       position.y = float.Parse(d[2]); 
       players[int.Parse(d[0])].avatar.transform.position = position; 
      } 
     } 

     // Send local client position 
     Vector3 myPosition = players[ourClientID].avatar.transform.position; 
     string m = "MYPOSITION" + myPosition.x.ToString() + '|' + myPosition.y.ToString(); 
     Send(m, unreliableChannel); 
    } 

    private void SpawnPlayer(string playerName, int cnnId, Texture2D animalTex, string animalType) 
    { 
     GameObject go = Instantiate(playerPrefab) as GameObject; 

     // Is this ours? 
     if (cnnId == ourClientID) 
     { 
      // Add mobility 
      go.AddComponent<PlayerMovement>(); 

      // Remove Canvas 
      GameObject.Find("Canvas").SetActive(false); 
      isStarted = true; 
     } 

     Player p = new Player(); 
     p.avatar = go; 
     p.playerName = playerName; 
     p.connectionId = cnnId; 
     p.avatar.GetComponentInChildren<TextMesh>().text = playerName; 
     p.animalTex = animalTex; 
     p.animalType = animalType; 
     players.Add(cnnId, p); 
    } 

    private void PlayerDisconnected(int cnnId) 
    { 
     Destroy(players[cnnId].avatar); 
     players.Remove(cnnId); 
    } 

    private void Send(string message, int channelID) 
    { 
     Debug.Log("Sending : " + message); 
     byte[] msg = Encoding.Unicode.GetBytes(message); 
     NetworkTransport.Send(hostID, connectionID, channelID, msg, message.Length * sizeof(char), out error); 
    } 
} 
+0

안녕하세요, 당신이 말한 튜토리얼에 대한 링크를 제공 할 수있다? – Fiffe

+0

안녕하세요. @Fiffe 튜토리얼 링크, https://www.youtube.com/watch?v=qGkkaNkq8co – greyBow

+0

감사합니다. @greyBow – Fiffe

답변

1

은 단순히이, 직렬화 및 데이터를 누른 뒤 수신하고 그것을 해제 직렬화 보낼 수 있습니다. 당신은 여전히 ​​혼란스러워하는 경우 아래의 단계 읽기 : 당신의 예에서

을, 당신은 Texture2D를 보낼과 string :

1 좁은 방 단계를 표현하는 것입니다

는 송신 측 클래스 나 구조체에 보낼 데이터.

이 클래스에 직접 Texture2D을 직접 추가하고 싶지는 않습니다. 그것을 바이트 배열로 저장해야합니다. 이 예제에서는 Texture2D.GetRawTextureData()을 사용합니다. 크기를 줄이려면 PNG 또는 JPEG 바이트 배열로 변환 할 수도 있습니다.

[Serializable] 
public class SendStructure 
{ 
    public byte[] texture; 
    public string message; 

    public SendStructure(Texture2D texture, string message) 
    { 
     this.texture = texture.GetRawTextureData(); 
     this.message = message; 
    } 
} 

2 .Serialize 데이터를 보낼 : 데이터의

예를 보낼 :

SendStructure sendStructure = new SendStructure(textureToSend, stringToSend); 
:

Texture2D textureToSend = new Texture2D(4, 4); 
string stringToSend = "Hello"; 

는하여 Texture2D에서 sturcture 및 문자열의 새로운 인스턴스를 생성

메모리에 직렬화

MemoryStream memStream = new MemoryStream(); 
IFormatter formatter = new BinaryFormatter(); 
formatter.Serialize(memStream, sendStructure); 

//Array data to send over network 
byte[] serializedStructure = memStream.ToArray(); 

.네트워크 전송

NetworkTransport.Send(hostID, sc.connectionID, channelID, serializedStructure, serializedStructure.Length, out error); 

수신 측 :

,691,363 :

5 .de는 일련 화 데이터를 수신

int outHostId; 
int outConnectionId; 
int outChannelId; 

int receivedSize; 
byte error; 

//Where to store received data 
byte[] buffer = new byte[400000]; 

NetworkEventType evt = NetworkTransport.Receive(out outHostId, out outConnectionId, out outChannelId, buffer, buffer.Length, out receivedSize, out error); 
네트워크

4 .Receive

이 (가) string 검색 :210

switch (evt) 
{ 
    case NetworkEventType.DataEvent: 
     { 
      //De-Serialize recevied byte array into memory 
      MemoryStream stream = new MemoryStream(buffer, 0, receivedSize); 
      IFormatter formatter = new BinaryFormatter(); 
      stream.Seek(0, SeekOrigin.Begin); 

      //Received data now stored as SendStructure 
      SendStructure receivedStructure = formatter.Deserialize(stream) as SendStructure; 

      break; 
     } 
} 

6 .Access 데이터 수신

string receivedString = receivedStructure.message; 

가 검색을 Texture2D :

Texture2D receivedtexture = new Texture2D(4, 4); 
receivedtexture.LoadRawTextureData(receivedStructure.texture); 
receivedtexture.Apply();