Unityは、単純なネットワーク同期エンジンNetgoを達成します
現在、特にネットワークプログラミングでは、人気の傾向をGOLANG。GCは、マシンのパフォーマンスの一部が、小さな誤り確率を占めるものの、およびC / C ++と比較するので、非常に簡単に非常に同時サーバープログラムを開発することができコルーチンのためのネイティブサポートの開発効率やアプリケーションを強化します。私は、より多くの2年以上のビジネスの連絡先の統一ネットワークエンジンの数をVR業界に連絡し、私は物事が簡単なエンジンを書いた後、で遅れたと感じました。現在、それは基本的な機能を実装します。
- 部屋の概念をサポートしています。
- これは、フレーム同期とRPCを含む柔軟なデータ同期をサポートしています。
- カスタムイベントの送信をサポートしています。
以下に示すように、より詳しくは、後であり、簡単なデモ、同期効果を達成しました。
プロジェクト住所:https://github.com/netgo-framework
ここでは、単純なプロジェクトのリカバリディスクです。
データ通信フォーマット
データ通信のフォーマットを定義することは、プロジェクト全体の基礎となるものです。ここでは、クライアントとサーバーは、クロスプラットフォーム、クロス言語コミュニケーションです。そのため、効率的なデータ形式は、トラフィックがかからない、簡単に使用する言語に依存しない、プラットフォームに依存しないとを定義します。ここでは、GoogleのいるProtobuf、詳細なリファレンスを使用し、このポスト。
C#のコードベースのいるProtobuf、2つのオプションがあり、一方がいるProtobuf-NET、一方がいるProtobuf-CSHARPポート、前者はC#構文仕様で記述された、より一貫性のあるインタフェースで、人々がより快適に見えるようになります。あなたは、クロスプラットフォームが必要な場合、より多くの同様の異なる言語で記述されたインタフェースは、開発が容易になりますので、後者を使用することをお勧めします。原作者の見てください回答を。
プロト・ファイルの定義
いるProtobufは、それを使用する方法を、私たちは、netgoで、以下はnetgo定義されたメッセージ本文の一部であり、独自の構造化データを最初の書き込みプロトファイルを定義する必要があります。
enum CacheOptions{
AddToRoomCache = 0;
RemoveFromRoomCache = 1;
}
message NGVector3{
float x = 1;
float y = 2;
float z = 3;
}
message NGQuaternion{
float x = 1;
float y = 2;
float z = 3;
float w = 4;
}
message NGColor{
float r = 1;
float g = 2;
float b = 3;
float a = 4;
}
完全な定義を参照。
C#とgolangのAPIインタフェースファイルを生成
名前空間の良いを更新した後、APIドキュメントを生成するには、次のコマンドを実行します。
golang
protoc --go_out =。* .proto
C#
protoc --csharp_out =。* .proto
サーバーのネットワークモデル
ユニティネットワーク同期エンジンは2つの部分で、サーバとクライアントが含ま達成。ネゴは golangが高い並列性を実現するために、そのネイティブコルーチンをフルに活用を実現使用してユニティネットワーク同期サーバエンジンです。基づいて、同社のネットワークモデルgotcpを実現しています。
図を参照すると、Netgoはコルーチン3つの内部の駆動ソケットHSを確立し、各コルーチンリンク用のソケットを作成します。
- ネットワークからのデータを読み取り、チャンネル内に置かについてReadLoop。
- HandleLoopチャネルを介しWriteLoopに処理されたデータをアプリケーション層データを解析し、対応する処理が完了し、送信のために。
- 責任前方クライアントまたはこのクライアントに他の応答に対する処理結果をWriteLoop。
リファレンスコード:
func (c *Conn) Do() {
if !c.srv.callback.OnConnect(c) {
return
}
asyncDo(c.handleLoop, c.srv.waitGroup)
asyncDo(c.readLoop, c.srv.waitGroup)
asyncDo(c.writeLoop, c.srv.waitGroup)
}
クライアントコードの構造
書き込みAPIは基本的に、ユーザ指向プログラミング、私が思うに、明確なコード構造、優れたコメントの大半を保存することが命名され、混乱は唯一の救助にコードを書かれたコメントに頼ることができ、コードの構造を見て:
ライブラリ、ネットワーク層及びアプリケーション層に名前空間に従って(レイヤユーザインターフェースはアウト分割された後)。
関連概念
データの同期
ここで同期が部屋内のデータの同期を参照して、ネットワーク上の複数のエンドユーザからメモリ内の部屋には、各クライアントには、クローンを作るために、ローカルの部屋データに他の人になり、データの同期はあなたに言及します自分の他のCient上記あなたのクローンへのデータ同期、および他のユーザーのため、伝送範囲が受信されています。
データ同期は約2種類に分かれています。
- ビューの同期
ビューSyncは、同期データミリ秒です。仮想キャラクタの動作を同期させるために使用することができます。
- RPC
各時間同期は、ユーザによって手動でトリガされます。同期は、のような服を着せるために使用することができます。
カスタムイベント
カスタムイベントは、他のクライアントのクローンエンティティのすべてに同期メッセージを送信しないのではなく、1つのまたは複数の特定のクライアントは、メッセージを送信します。
インターフェイス説明
ルーム依存インタフェース
リクエストインターフェイス
//加入或者创建房间
public static void JoinOrCreateRoom(string roomid,uint maxnumber)
//创建房间
public static void CreateRoom(string roomid, uint maxnumber)
//加入房间
public static void JoinRoom(string roomid)
//离开房间
public static void LeaveRoom()
コールバックインタフェース
//创建房间成功
void OnGreatedRoom();
//创建房间失败
void OnGreateRoomFailed(string errmsg);
//加入房间成功
void OnJoinedRoom();
//加入房间失败
void OnJoinRoomFailed();
//离开房间成功
void OnLeftRoom();
プレイヤー関連のインターフェイス
//实例化一个物体
public static void Instantiate(string prefabname, Vector3 position, Quaternion rotation, uint[] viewids)
//有其它用户进入房间
void OnOtherPlayerEnteredRoom(NGPlayer player);
//有其它用户离开房间
void OnOtherPlayerLeftRoom(NGPlayer player);
CustomEventインタフェース
リクエストインターフェイス
//发送事件
public static void SendCustomEvent(uint eventid, uint[] targetpeerids, NGAny[] customdata)
コールバックインタフェース
//接收事件
void OnCustomEvent(uint eventID, NGAny[] data);
ビューの同期
同期コンポーネントスクリプトを達成するために彼らの必要性を考慮、シリアライズデシリアライズインタフェースを実装し、対象物に装着される必要があります。
public interface INGSerialize
{
void SerializeViewComponent(NGViewStream stream);
void DeserializeViewComponent(NGViewStream stream);
}
public class CubeViewComponent : NGIncomingEvent, INGSerialize
{
public void SerializeViewComponent(NGViewStream stream)
{
stream.Send(this.transform.position);
stream.Send(this.transform.rotation);
}
public void DeserializeViewComponent(NGViewStream stream)
{
mCorrentPosition = (NGVector3)stream.Receive();
mCorrentRotation = (NGQuaternion)stream.Receive();
}
}
データを受け入れるためのクローンエンティティがにアップデートしてリアルタイムの更新を直列化復元しました:
void Update()
{
if (!view.IsMine)
{
transform.position = mCorrentPosition;//Vector3.Lerp(transform.position, mCorrentPosition, Time.deltaTime * 5);
transform.rotation = mCorrentRotation;//Quaternion.Lerp(transform.rotation, mCorrentRotation, Time.deltaTime * 5);
}
}
RPC
RPCは、ビュースクリプトで関数を記述するためにRPCの必要性を使用しています。
[NGRPCMethod]
public void OnColor(NGAny[] c)
{
mMat.color = c[0].NgColor;
}
他のエンティティのクローンにRPCコールを送信するには、次のインターフェイスを呼び出します。
public static void SendRPC(uint viewID, string methodname, RPCTarget target, params NGAny[] parameters)
RPC、ビュー同期カスタムイベントとの使用についての詳細参照元
Demo演示
Serverの展開
クローンコード
git clone https://github.com/netgo-framework/netgo.git
インストールが依存します
go get -d ./...
更新モニタIP
オープンmain.go
tcpAddr, err := net.ResolveTCPAddr("tcp", "192.168.0.104:8686")
サービス開始
go run main.go
クライアントをコンパイルしてインストールします
クライアントのサポートWindows / MacOSの/ Andorid / IOSの複数のプラットフォーム。Androidと次のテストでのMacOS:
設定IPとポート
Androidプラットフォームを切り替えます
コンパイルされたAPK
次のようにAPKインターフェイス初期化した後にインストールされています。
機能テスト
同じ部屋に2つのクライアントは、各クライアントは2キューブ、ネイティブのエンティティ(鉱山キューブ)、エンティティ(クローンキューブ)のパートナーをインスタンス化します。
ビューの同期
ボタンのクリック移動背中を、同期ビューの仕方によってpostionと回転を同期されます。それは道を示すマップを移動する資料の冒頭です。
RPC
色同期がRPCを介して達成される他のマシンに同期しながら、鉱山キューブをクリックした後、キューブは、色を変更します。
カスタムイベント
クローンキューブをクリックした後、他のエンティティにメッセージを送信し、効果が大きくなります鉱山キューブスケールの反対側です。
ロードマップ
次の考慮事項は、最適化や追加機能が必要になります。
- サポート機能ホール
- サポート負荷分散
- ネットワークなどのUDPトランスポートプロトコルのサポートが追加されました
- サポートが追加されましたが、JSONやその他のデータの符号化形式
- ビュー同期データ転送の最適化
- 部屋のカスタムイベント全体をサポート
- .....