最初に少しコンテキスト:私はScala(ファーストパーソンシューティングゲームのような)でクライアント/サーバーゲームを書いています。クライアントは1秒間に数十回サーバーに移動の意図を送信する必要があり、サーバーはエンティティの状態を送り返します。リアルタイムでも。クライアント側(グラフィカルな流動性のため)とサーバー側の両方でJBulletを使用して、これらのエンティティの物理シミュレーションがあります。クライアントがサーバーから更新を受信するたびに、クライアントはそのローカル状態をサーバーが送信した状態に置き換えます。もちろん、特定の瞬間に同じサーバー上に多くのクライアントが存在する可能性があります。要するに、このアプリケーションでは、通信は小さなパケットで頻繁に発生します。
現在、私はAkkaのアクターを使用して、Scalaケースクラスをネットワーク経由でサーバーに素朴に送受信しています。次に例を示します。
sealed trait PlayerMessage
case class PlayerMove(dir: Vector3, run: Boolean) extends PlayerMessage
// more case classes...
次に、クライアントで:
server ! PlayerMove(dir, run)
サーバー上:
def receive = {
case pm: PlayerMessage => pm match {
case p @ PlayerMove(dir, run) =>
// Move the player
world.playerMove(dir,run)
// More case tests..
}
// Send back entity states (this in fact occurs elsewhere, asynchronously)
world.entities.foreach(ent => client ! ent.state()))
// More message testing ...
case _ => // ignore
}
ent.stateがEntityStateを返す場合:
case class BulletState(pos: Vector3, quat: Vector4, lin: Vector3, ang: Vector3)
sealed trait EntityState
case class EntityStatePlayer(id: Int, bullet: BulletState) extends EntityState
// more case classes...
これはすべてかなりうまく機能していますが、ご覧のとおり、他のケースクラスを含むケースクラスがたくさんあり、クライアントとサーバーの両方で一連のケーステストがあります。
- シリアル化、逆シリアル化、およびマッチングによるパケットサイズとオーバーヘッドの両方を削減するにはどうすればよいですか?
- ケースクラスの代わりにProtobufを使用すると、アプリケーションのパケットから脂肪が削減されますか?
- このネットワークプロトコルの改善のために間違った場所を見ていますか?