Unity Transport 入門(1) - シンプルなクライアント・サーバ間の通信
「Unity Transport」を使って、シンプルなクライアント・サーバ間で通信する方法を説明します。
・Unity 2019.3.14f1
・Unity Transport 0.3.1
1. プロジェクトの準備
(1) Unityプロジェクトを「3D」テンプレートで作成。
(2) メニュー「Window → Package Manager」で「Package Manager」を開く。
(3) ウィンドウ上部の「Advances → show preview packages」をチェック。
(4) 「Unity Transport」(0.3.1)を検索してインストール。
2. 今回のサンプル
今回のサンプルは、クライアントがサーバに接続し、番号を送信すると、この番号はサーバによって受信され、別の番号が追加されてクライアントに返送されます。クライアントは、番号を受信すると、接続を切断して終了します。
3. シーンの準備
Hierarchyウィンドウの「+ → Create Empty」で空のゲームオブジェクトを作成し、名前に「Sample」を指定します。
4. サーバーの生成
「Sample」にスクリプト「ServerBehaviour」を追加し、以下のように編集します。
using UnityEngine;
using UnityEngine.Assertions;
using Unity.Collections;
using Unity.Networking.Transport;
public class ServerBehaviour : MonoBehaviour
{
private NetworkDriver driver; // ドライバ
private NativeList<NetworkConnection> connections; // 接続情報リスト
// スタート時に呼ばれる
void Start ()
{
// ドライバの生成
this.driver = NetworkDriver.Create();
// エンドポイントの生成
var endpoint = NetworkEndPoint.AnyIpv4;
endpoint.Port = 9000;
// ドライバのバインド
if (this.driver.Bind(endpoint) != 0)
{
Debug.Log("ポート9000のバインド失敗");
}
else
{
// クライアントからの接続を待つ
this.driver.Listen();
}
// 接続情報リストの生成
this.connections = new NativeList<NetworkConnection>(16, Allocator.Persistent);
}
// 破棄時に呼ばれる
public void OnDestroy()
{
// ドライバの破棄
this.driver.Dispose();
// 接続情報リストの破棄
this.connections.Dispose();
}
// 1フレーム毎に呼ばれる
void Update ()
{
// 通信Jobの実行
this.driver.ScheduleUpdate().Complete();
// 接続情報の削除
for (int i = 0; i < this.connections.Length; i++)
{
if (!this.connections[i].IsCreated)
{
this.connections.RemoveAtSwapBack(i);
--i;
}
}
// 接続情報の追加
NetworkConnection c;
while ((c = this.driver.Accept()) != default(NetworkConnection))
{
this.connections.Add(c);
}
// 接続情報の反復
DataStreamReader stream;
for (int i = 0; i < this.connections.Length; i++)
{
Assert.IsTrue(this.connections[i].IsCreated);
// イベントの反復
NetworkEvent.Type cmd;
while ((cmd = this.driver.PopEventForConnection(this.connections[i], out stream)) != NetworkEvent.Type.Empty)
{
// データ受信
if (cmd == NetworkEvent.Type.Data)
{
// データ受信
uint value = stream.ReadUInt();
Debug.Log("サーバがクライアントから値" + value + "を受信");
// データ送信
value += 2;
var writer = this.driver.BeginSend(NetworkPipeline.Null, this.connections[i]);
writer.WriteUInt(value);
this.driver.EndSend(writer);
Debug.Log("サーバがクライアントに値" + value + "を送信");
}
// 切断
else if (cmd == NetworkEvent.Type.Disconnect)
{
Debug.Log("サーバがクライアントと切断");
this.connections[i] = default(NetworkConnection);
}
}
}
}
}
◎ NetworkEndPoint
「NetworkEndPoint」は、アドレスとポート番号を保持するエンドポイントです。
static NetworkEndPoint AnyIpv4 : サーバのエンドポイントの生成
static NetworkEndPoint LoopbackIpv4 : 接続先のエンドポイントの生成
ushort Port : ポート
string Address : アドレス
◎ NetworkDriver
「NetworkDriver」は接続するためのドライバです。
主なメソッドは次のとおりです。
◎ 接続
static NetworkDriver Create(params INetworkParameter[] param) : ドライバの生成
◎ クライアント接続
NetworkConnection Connect(NetworkEndPoint endpoint) : サーバーに接続
◎ サーバー接続
int Bind(NetworkEndPoint endpoint) : ドライバのバインド
int Listen() : クライアントからの接続を待つ
NetworkConnection Accept() : 接続情報の取得
◎ データ送信
DataStreamWriter BeginSend(NetworkConnection id, int requiredPayloadSize = 0) : データの送信開始
DataStreamWriter BeginSend(NetworkPipeline pipe, NetworkConnection id, int requiredPayloadSize = 0) : データの送信開始
int EndSend(DataStreamWriter writer) : データの送信完了
◎ データ受信
NetworkEvent.Type PopEventForConnection(NetworkConnection connectionId, out DataStreamReader reader) : イベントのポップ
◎ Jobの実行
JobHandle ScheduleUpdate(JobHandle dep = null) : 通信Jobの実行
◎ 切断
void Dispose() : 切断
◎ NetworkConnection
「NetworkConnection」はクライアント接続時に取得する接続情報です。
主なプロパティとメソッドは次のとおりです。
bool IsCreated : 接続中かどうか
PopEvent(NetworkDriver, out DataStreamReader) : イベントのポップ
◎ NetworkEvent.Type
ネットワークイベント種別は、次のとおりです。
・NetworkEvent.Type.Connect : 接続
・NetworkEvent.Type.Data : データ受信
・NetworkEvent.Type.Disconnect : 切断
・NetworkEvent.Type.Empty : 空
◎ Jobの実行
「NetworkDriver」の通信処理は、「C# Job System」で実行します。
Update()で以下のようにジョブを実行します。
m_Driver.ScheduleUpdate().Complete();
5. クライアントの生成
「Sample」にスクリプト「ClientBehaviour」を追加し、以下のように編集します。
using UnityEngine;
using Unity.Networking.Transport;
public class ClientBehaviour : MonoBehaviour
{
private NetworkDriver driver; // ドライバ
private NetworkConnection connection; // 接続
private bool done; // 完了
// スタート時に呼ばれる
void Start()
{
// ドライバの生成
this.driver = NetworkDriver.Create();
// エンドポイントの生成
var endpoint = NetworkEndPoint.LoopbackIpv4;
endpoint.Port = 9000;
// サーバーとの接続
this.connection = this.driver.Connect(endpoint);
}
// 破棄時に呼ばれる
public void OnDestroy()
{
// ドライバの破棄
this.driver.Dispose();
}
// 1フレーム毎に呼ばれる
void Update()
{
// Jobの実行
this.driver.ScheduleUpdate().Complete();
// 切断
if (!this.connection.IsCreated)
{
return;
}
// イベントの反復
DataStreamReader stream;
NetworkEvent.Type cmd;
while ((cmd = this.connection.PopEvent(this.driver, out stream)) != NetworkEvent.Type.Empty)
{
// 接続
if (cmd == NetworkEvent.Type.Connect)
{
Debug.Log("クライアントがサーバと接続");
// データの送信
uint value = 1;
Debug.Log("クライアントがサーバに値" + value + "を送信");
var writer = this.driver.BeginSend(this.connection);
writer.WriteUInt(value);
this.driver.EndSend(writer);
}
// データの受信
else if (cmd == NetworkEvent.Type.Data)
{
// データの受信
uint value = stream.ReadUInt();
Debug.Log("クライアントがサーバから値" + value + "を受信");
// 切断の実行
this.done = true;
this.connection.Disconnect(this.driver);
this.connection = default(NetworkConnection);
}
// 切断
else if (cmd == NetworkEvent.Type.Disconnect)
{
// 切断の完了
Debug.Log("クライアントがサーバと切断");
this.connection = default(NetworkConnection);
}
}
}
}
6. 実行
コンソールに以下のように結果が表示されます。
この記事が気に入ったらサポートをしてみませんか?