Unity Transport入門

投稿忘れていたものを投稿

## サーバーループ（同期バージョン）
NetworkConnectionは複数持つ（`NativeList<>`）

transportのjob systemでScheduleUpdateを呼び出す→JobHandleが返される
`Complete()`→実行プロセスを開始して完了まで待つ（必ず呼び出す必要がある）

```
m_Driver.ScheduleUpdate().Complete();
```

### 古い接続を処理
`NetworkConnection.IsCreated`でコネクションが終了しているかどうかを判定できる

```
// Clean up connections
for (int i = 0; i < m_Connections.Length; i++)
{
    if (!m_Connections[i].IsCreated)
    {
        m_Connections.RemoveAtSwapBack(i);
        --i;
    }
}
```

### 新しい接続を処理
`NetworkDriver.Accept`で新しいコネクションを取得できる

```
// Accept new connections
NetworkConnection c;
while ((c = m_Driver.Accept()) != default(NetworkConnection))
{
    m_Connections.Add(c);
    Debug.Log("Accepted a connection");
}
```

### イベントを処理
`DataStreamReader`：Dataイベントが受信された場合に使用される
`PopEventForConnection`: 接続ごとに受信したイベントを処理できる

```
NetworkEvent.Type cmd;
while ((cmd = m_Driver.PopEventForConnection(m_Connections[i], out stream)) != NetworkEvent.Type.Empty)
{
...
```

#### イベントのタイプ

````NetworkEvent.Type.Data
public enum Type
{
    Empty = 0,
    Data = 1,
    Connect = 2,
    Disconnect = 3
}
```
となっており、上記の4種類がある

#### データを取得する
`DataStreamReader.ReadUInt`

DataStreamReaderではbyteやintなどのデータ型を受信する。stringなども取得できる

#### データを送信する
`DataStreamWriter writer;`DataStreamWriterを定義する
`NetworkDriver.BeginSend(NetworkPipeline, NetworkConnection, out writer)`: DataStreamWriterを取得する

DataStreamWriterではbyteやintなどのデータ型を送信できる。stringなども送れる

`WriteUInt`でInt値を追加する
`NetworkDriver.EndSend`: 追加を終了し、送信する

#### 切断処理

`NetworkEvent.Type.Disconnect`の場合は切断のリクエスト
`default(NetworkConnection)`でコネクションをリセットする（`IsCreated`が`false`になるので次のループで削除される）

## クライアント
NetworkConnectionは一つだけ

### 接続

`NetworkDriver.Connect`でサーバーに接続する

### イベントを処理

`NetworkConnection.PopEvent`を使う（単一の処理をしていることを明確にする）

`NetworkEvent.Type.Connect`: リモートピアに接続されたことを通知する


## クライアントループ（非同期バージョン）
`IJob`を使う。`Driver`や`NetworkConnection`はコピーして使用しなければならない。


## サーバーループ（非同期バージョン）
`IJobParallelForDefer`を使う。しかし、接続時の処理などは非同期で行うことができないため、イベントを処理するjobと接続を処理するjobを分ける必要がある。

`IJobParallelForDefer`では`Execute`でconnectionsのindexを取得できる。

## パイプライン
> パイプラインは、デフォルトのソケット実装動作の上に機能のレイヤーを提供する機能です。UDPソケットの場合、これにより、シーケンス、信頼性、断片化などのサービス品質機能など、標準の信頼性の低いデータグラムに加えて追加機能を使用できます。これは、ドライバーで使用するために実装されている任意のタイプのソケットインターフェイスで機能する可能性があります。

> ドライバには、すべての組み込みパイプラインステージがすでに構成されているデフォルトのコレクションが用意されています。コレクションに追加する必要がある独自のパイプラインステージがある場合は、それを使用してカスタムコレクションを使用することができます。

> したがって、クライアントとサーバーの両方がまったく同じ方法でパイプラインを設定することが重要です

`NetworkPipeline`: パイプラインを定義する（内部的にはただのhash）

### 使用例
`SimulatorPipelineStage`: ネットワークの状況をシュミレーションできる（シュミレーションする側のみ追加すれば良い）

`UnreliableSequencedPipelineStage`: パケットが正常に配信されることを確認する

### パイプラインの使用方法

`NetworkDriver.CreatePipeline`でパイプラインを作成できる。`typeof`で指定したパイプラインの処理を実行してから送信するようになる。（同じパイプラインは複数追加できない）

`BeginSend`でパイプラインを指定する。（クライアントとサーバーで同じパイプラインを設定しないとエラーになる）

`NetworkPipelineStageCollection.GetStageId`でstage_idを取得できる


## 更新のフロー
![com.unity.transport.driver.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475516/0792e650-a9d5-af34-0c22-a03ee4182de7.png)

https://docs.unity3d.com/Packages/com.unity.transport@0.6/manual/update-flow.html より引用


## 接続のステート遷移

![com.unity.transport.connection.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475516/be800ce8-64f6-813f-57df-dcdb6e653ecf.png)

https://docs.unity3d.com/Packages/com.unity.transport@0.6/manual/connection-state-machine.html より引用