Unity 멀티플레이어 서비스를 통합할 때 최대한의 유연성이 필요할 경우 NetworkTransport
클래스를 직접 사용할 수 있습니다. 이 메서드는 더 많은 코드가 필요하지만, 게임이 멀티플레이어 서비스와 통합되는 방법을 보다 세부적으로 제어할 수 있습니다.
다음은 NetworkTransport
클래스를 사용하여 직접 연결할 수 있는 방법에 대한 예제입니다.
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Networking.Types;
using UnityEngine.Networking.Match;
using System.Collections.Generic;
public class DirectSetup : MonoBehaviour
{
// Matchmaker related
List<MatchInfoSnapshot> m_MatchList = new List<MatchInfoSnapshot>();
bool m_MatchCreated;
bool m_MatchJoined;
MatchInfo m_MatchInfo;
string m_MatchName = "NewRoom";
NetworkMatch m_NetworkMatch;
// Connection/communication related
int m_HostId = -1;
// On the server there will be multiple connections, on the client this will only contain one ID
List<int> m_ConnectionIds = new List<int>();
byte[] m_ReceiveBuffer;
string m_NetworkMessage = "Hello world";
string m_LastReceivedMessage = "";
NetworkWriter m_Writer;
NetworkReader m_Reader;
bool m_ConnectionEstablished;
const int k_ServerPort = 25000;
const int k_MaxMessageSize = 65535;
void Awake()
{
m_NetworkMatch = gameObject.AddComponent<NetworkMatch>();
}
void Start()
{
m_ReceiveBuffer = new byte[k_MaxMessageSize];
m_Writer = new NetworkWriter();
// While testing with multiple standalone players on one machine this will need to be enabled
Application.runInBackground = true;
}
void OnApplicationQuit()
{
NetworkTransport.Shutdown();
}
void OnGUI()
{
if (string.IsNullOrEmpty(Application.cloudProjectId))
GUILayout.Label("You must set up the project first. See the Multiplayer tab in the Service Window");
else
GUILayout.Label("Cloud Project ID: " + Application.cloudProjectId);
if (m_MatchJoined)
GUILayout.Label("Match joined '" + m_MatchName + "' on Matchmaker server");
else if (m_MatchCreated)
GUILayout.Label("Match '" + m_MatchName + "' created on Matchmaker server");
GUILayout.Label("Connection Established: " + m_ConnectionEstablished);
if (m_MatchCreated || m_MatchJoined)
{
GUILayout.Label("Relay Server: " + m_MatchInfo.address + ":" + m_MatchInfo.port);
GUILayout.Label("NetworkID: " + m_MatchInfo.networkId + " NodeID: " + m_MatchInfo.nodeId);
GUILayout.BeginHorizontal();
GUILayout.Label("Outgoing message:");
m_NetworkMessage = GUILayout.TextField(m_NetworkMessage);
GUILayout.EndHorizontal();
GUILayout.Label("Last incoming message: " + m_LastReceivedMessage);
if (m_ConnectionEstablished && GUILayout.Button("Send message"))
{
m_Writer.SeekZero();
m_Writer.Write(m_NetworkMessage);
byte error;
for (int i = 0; i < m_ConnectionIds.Count; ++i)
{
NetworkTransport.Send(m_HostId,
m_ConnectionIds[i], 0, m_Writer.AsArray(), m_Writer.Position, out error);
if ((NetworkError)error != NetworkError.Ok)
Debug.LogError("Failed to send message: " + (NetworkError)error);
}
}
if (GUILayout.Button("Shutdown"))
{
m_NetworkMatch.DropConnection(m_MatchInfo.networkId,
m_MatchInfo.nodeId, 0, OnConnectionDropped);
}
}
else
{
if (GUILayout.Button("Create Room"))
{
m_NetworkMatch.CreateMatch(m_MatchName, 4, true, "", "", "", 0, 0, OnMatchCreate);
}
if (GUILayout.Button("Join first found match"))
{
m_NetworkMatch.ListMatches(0, 1, "", true, 0, 0, (success, info, matches) =>
{
if (success && matches.Count > 0)
m_NetworkMatch.JoinMatch(matches[0].networkId, "", "", "", 0, 0, OnMatchJoined);
});
}
if (GUILayout.Button("List rooms"))
{
m_NetworkMatch.ListMatches(0, 20, "", true, 0, 0, OnMatchList);
}
if (m_MatchList.Count > 0)
{
GUILayout.Label("Current rooms:");
}
foreach (var match in m_MatchList)
{
if (GUILayout.Button(match.name))
{
m_NetworkMatch.JoinMatch(match.networkId, "", "", "", 0, 0, OnMatchJoined);
}
}
}
}
public void OnConnectionDropped(bool success, string extendedInfo)
{
Debug.Log("Connection has been dropped on matchmaker server");
NetworkTransport.Shutdown();
m_HostId = -1;
m_ConnectionIds.Clear();
m_MatchInfo = null;
m_MatchCreated = false;
m_MatchJoined = false;
m_ConnectionEstablished = false;
}
public virtual void OnMatchCreate(bool success, string extendedInfo, MatchInfo matchInfo)
{
if (success)
{
Debug.Log("Create match succeeded");
Utility.SetAccessTokenForNetwork(matchInfo.networkId, matchInfo.accessToken);
m_MatchCreated = true;
m_MatchInfo = matchInfo;
StartServer(matchInfo.address, matchInfo.port, matchInfo.networkId,
matchInfo.nodeId);
}
else
{
Debug.LogError("Create match failed: " + extendedInfo);
}
}
public void OnMatchList(bool success, string extendedInfo, List<MatchInfoSnapshot> matches)
{
if (success && matches != null)
{
m_MatchList = matches;
}
else if(!success)
{
Debug.LogError("List match failed: " + extendedInfo);
}
}
// When we've joined a match we connect to the server/host
public virtual void OnMatchJoined(bool success, string extendedInfo, MatchInfo matchInfo)
{
if (success)
{
Debug.Log("Join match succeeded");
Utility.SetAccessTokenForNetwork(matchInfo.networkId, matchInfo.accessToken);
m_MatchJoined = true;
m_MatchInfo = matchInfo;
Debug.Log("Connecting to Address:" + matchInfo.address +
" Port:" + matchInfo.port +
" NetworKID: " + matchInfo.networkId +
" NodeID: " + matchInfo.nodeId);
ConnectThroughRelay(matchInfo.address, matchInfo.port, matchInfo.networkId,
matchInfo.nodeId);
}
else
{
Debug.LogError("Join match failed: " + extendedInfo);
}
}
void SetupHost(bool isServer)
{
Debug.Log("Initializing network transport");
NetworkTransport.Init();
var config = new ConnectionConfig();
config.AddChannel(QosType.Reliable);
config.AddChannel(QosType.Unreliable);
var topology = new HostTopology(config, 4);
if (isServer)
m_HostId = NetworkTransport.AddHost(topology, k_ServerPort);
else
m_HostId = NetworkTransport.AddHost(topology);
}
void StartServer(string relayIp, int relayPort, NetworkID networkId, NodeID nodeId)
{
SetupHost(true);
byte error;
NetworkTransport.ConnectAsNetworkHost(
m_HostId, relayIp, relayPort, networkId, Utility.GetSourceID(), nodeId, out error);
}
void ConnectThroughRelay(string relayIp, int relayPort, NetworkID networkId, NodeID nodeId)
{
SetupHost(false);
byte error;
NetworkTransport.ConnectToNetworkPeer(
m_HostId, relayIp, relayPort, 0, 0, networkId, Utility.GetSourceID(), nodeId, out error);
}
void Update()
{
if (m_HostId == -1)
return;
var networkEvent = NetworkEventType.Nothing;
int connectionId;
int channelId;
int receivedSize;
byte error;
// Get events from the relay connection
networkEvent =