LoginSignup
31

More than 3 years have passed since last update.

RustでgRPCで簡易マルチプレイサーバー書いてUnityで動かしてみた

Last updated at Posted at 2020-04-06

こんにちは、あんはるです!

コロナで暇なので、紹介してなかったプロジェクトを紹介したいと思います.

突然ですけど、このGIF見てみてください.
右のウィンドウと左のウィンドウはサーバー経由で座標を共有しあっています〜
これが簡易マルチプレイです!
image.png

きっかけ・目的

荒野行動を始めると、100人のユーザーがリアルタイムに走っててすごいなぁと思いました。どうやったらこんなサーバ作れるのだろうという興味がきっかけです。

とりあえず、自前で実装してみたい!となったのでやってみます。

 このプロジェクトの構成

バックエンド

  • gRPC
  • MongoDB

フロントエンド

  • Unity

です。
上のデモはローカルで完結させてます。

なぜgRPC?

Unityで、リアルタイムに処理したいという時に、MagicOnion – C#による .NET Core/Unity 用のリアルタイム通信フレームワークがよく記事に書かれています。

MagicOnionの通信は、gRPCを用いています。

また、Protocol BufferでRPCの定義をするだけで、ホスト、クライアントのコードが生成されることに無駄のなさを感じでクールだなと感じだので、使ってみたいと思いました。

なぜMongoDB?

速度が求められるので。

マルチプレイサーバー

ソースコードは、https://github.com/anharu2394/multiplay-grpc-server

Rustで書いてみた

このプロジェクトを書いた当時、一番Githubスター数が多かったgrpc-rsを使いました。

Protocol Bufferでマルチプレイサーバーの使用を定義。
UserPositionは、ユーザーのidとどこにいるかを表しています。
ConnectPositionで双方向ストリーミングで座標を同期しています。

multiplay.proto
syntax = "proto3";
package anharu;

service Multiplay {
  rpc GetUsers(GetUsersRequest) returns (stream GetUsersResponse);
  rpc SetPosition(stream SetPositionRequest) returns (SetPositionResponse);
  rpc ConnectPosition(stream ConnectPositionRequest) returns (stream ConnectPositionResponse);
}

message GetUsersRequest {
  string room_id = 1;
}

message GetUsersResponse {
  repeated UserPosition users = 1; 
}

message UserPosition {
  string id = 1;
  double x = 2;
  double y = 3;
  double z = 4;
}

message SetPositionRequest {
  string id = 1;
  double x = 2;
  double y = 3;
  double z = 4;
}

message SetPositionResponse {
  string status = 1;
  string id = 2;
  string error = 3;
}

message ConnectPositionRequest {
  string id = 1;
  double x = 2;
  double y = 3;
  double z = 4;
}

message ConnectPositionResponse {
  repeated UserPosition users = 1; 
}

service User {
  rpc Create (CreateUserRequest) returns (CreateUserResponse);
}

message CreateUserRequest {
  string name = 1;
}
message CreateUserResponse {
  string id = 1;
}

そして、protoから生成されたコードを使って、それぞれ実装していきました。

マルチプレイクライアント

ソースコードは、 https://github.com/anharu2394/multiplay-grpc-client
Unityなのでc#で書いてます。

Unityはそもそも、gRPCを使う環境を整えるのに時間がかかりました...

https://note.com/npaka/n/n050b1aba7772
これを参考にすると分かりやすいと思います!

ストリーミングして、サーバーから座標が送られてくるごとに、キャラクターの座標を更新するという感じでやりました!

サーバーの動作確認がしたいだけなので、UIや見た目などは超手抜きですが、ジャンプのアニメーションをつけたり少しゲームっぽくして見ました!

 まとめ

おそらく、本番環境では使い物にはならないかもしれませんが、ローカルの中でもgRPCの双方向ストリーミングが体感できてよかったです〜〜

RustもgRPCも頑張ります〜〜!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31