はじめに
先日、かねてより開発していたゲームをSteamにてリリースしました。
個人制作としては比較的規模の大きいゲームになったこともあり、技術面・ゲーム制作面のどちらでも多くの工夫や苦労がありました。
この記事では、これからゲーム制作をしてみたい方や、個人開発でオンラインゲームを作ることに興味がある方向けに、私の体験談を交えながら制作内容を紹介していきます。
全部で10 ~ 15回となる想定です。
初回となる今回は、ゲームの紹介と全体アーキテクチャの概要について書いていきます。
制作物『Caldra』について
こちらのゲームは2人対戦のカードバトルゲームとなっています。
技術的な観点から見ると、このゲームでは主に以下のような機能が必要になります。
- 2人対戦であるため、通信処理が必要
- 大量のカードデータと、それぞれのカード効果を実装する必要がある
- 対戦中の状態を管理するため、ゲームサーバが必要
- ユーザ名やアイコンなどのプレイヤー情報を管理する必要がある
- 個人制作かつ無名のタイトルなので、大量アクセスは想定しない
- 正直、想定が外れて大量アクセスが来てくれた方が嬉しいですが……
このような要件を満たすために、クライアント・サーバ構成を取り、AWS上にゲーム用のサーバを構築することにしました。
全体のアーキテクチャ
全体の構成は、ざっくり以下のようになっています。

(アーキテクチャ図、特にAWS周りがかなり簡略化されている点は多めに見てほしいです・・・)
先ほど挙げた要件を見ると、通信が必要であることは明らかでした。
特に今回は、ゲームロジックが比較的複雑であり、ユーザ管理も必要だったため、P2Pではなくクライアント・サーバ形式を採用しました。
そのため、AWS上にサーバを立て、プレイヤーはそのサーバに接続して対戦を行う形にしています。
サーバマシン
各サービスのプログラムを動かすためのLinuxマシンです。インスタンスタイプは t3a.small にしています、よわよわですね。ちなみに料金は1時間当たり0.0188ドルとの事です。お金まわりは別な回で解説しようと思いますが、サーバマシンはそこまで大きなコストは掛かっていません。
サーバマシンは2台用意していますが、ユーザが接続するのは基本的に片方の1台のみです。
もう片方のサーバには、次回アップデート用の最新プログラムを配置し、私の方で動作確認を行うために使用しています。
動作確認が完了したら、ロードバランサの向き先を切り替えることで、ユーザが最新のサーバへ接続するようにしています。
このように2台構成にしておくことで、サービスを停止せずにサーバプログラムを更新できるようにしています。
いわゆるBlue-Green Deploymentに近い運用です。
ロビーサーバ・ゲームサーバ
サーバ側のプログラムは、大きく分けてロビーサーバとゲームサーバに分かれています。
ロビーサーバはユーザのログインやセッション管理、名前やアイコンなどを保存するために使用しています。
ゲームサーバはプレイヤーの操作やカード処理などのゲームの管理を行っています。このゲームの一番の肝です。カードゲームは見た目以上に状態管理が複雑で、「カードを使う」「攻撃する」「倒される」「効果が発動する」といった処理が連鎖的に発生します。そのため、ゲームの処理は全てサーバ側で管理するようにしています。
また、ログイン処理にはSteamのセッションチケットとSteamworks Web APIを使用しています。
これは、サーバ側でSteamユーザの認証を行い、なりすましを防ぐためです。
ロビーサーバ・ゲームサーバの実装にはどちらもRustを使用しています。Rustは言語の特性上実行速度やメモリ管理・並列処理・大規模開発などいろいろな面で優れているという噂を聞いて採用しました。実際書いてみると思いますが、Rustはその特有の書き方のルールによってこの手の不具合やパフォーマンス劣化が発生しにくい作りになっていそうです。
代わりにこの特有の書き方のルールによって初期の学習コストが高いですが、私はこの学習コストをAIの導入という無理やりな方法で解消しています![]()
ロードバランサ
ロードバランサは、通常であれば複数のサーバへアクセスを分散するために使用します。
ただし、今回の構成では、ユーザが接続するサーバは基本的に1台だけです。
そのため、負荷分散という意味ではロードバランサはほとんど仕事をしていません。
先ほどのサーバマシンの章で説明した通りシステムの最新化のために用いています
ゲーム画面
ゲーム画面はユーザの操作の受付やゲームの状態をプレイヤー向けに描写するという仕事を行っています。
ゲーム画面にはUnityを採用しています。これの採用理由としては「私が書けるから」という理由だけです。
ゲームエンジンには他にもUnreal EngineやGodotなどありますが、今回の規模だとサーバ側を作るだけでも結構時間が掛かる想定だったので、ゲームクライアント側で知らないエンジンを使うだけの工数を取る余裕が私に無かったのです・・・
個人開発では、技術的に最適な選択だけでなく、「自分が最後まで作り切れるか」もかなり重要だと思っています。
その意味で、Unityを選んだのはかなり現実的な判断でした。
管理用端末
ログやDBへのアクセスをGUIを用いて表示するために使用しています。
私がAWS上のリソースの管理を楽にするためだけにあるコンピュータなので、ゲームにはなにも関与していないですが管理におけるQoLは上がります。
実際にリリースしてみて
個人開発にしてはちゃんと組んだ方かなと思っています。特にAWSの構築は初めての経験なので分からずに組んでいる所も多かったですが、実際に組んでちゃんと動いたときはとても感動しました。
ユーザが実際にサーバへアクセスしているログを見ると、「本当にインターネット上で自分の作ったゲームが動いているんだな」という実感があります。やはりローカル環境でのテスト時では無い緊張感がありますね。
理想を言えば、もっと堅牢な構成にしたり、監視を強化したり、自動デプロイを整えたり、負荷試験をしたりしたいところです。
ただ、個人開発では時間もお金も限られています。
そのため、今回は「小規模なオンラインゲームとして現実的に運用できること」を優先しました。
大量アクセスを前提にした構成ではありませんが、少人数が遊ぶ分には十分動く構成を目指しています。
大変ではありましたが、かなり良い経験になりました。
終わりに
ゲームを制作してリリースするのは、時間も掛かりますし、面倒なことも多いです。
ただ、実際にやってみるととても楽しいです。
特に今回はAWS / Rustなど、初めて使う技術に触れる機会になったのでとても勉強になりました。
今後も不具合修正や改善を続けつつ、ゲーム自体もより良くしていきたいと思っています。
最後に、このゲームは無料でリリースしています。
もし興味を持っていただけたら、ぜひプレイしていただけると嬉しいです!
