サーバー"コード"レスアーキテクチャによるゲームクライアント開発 の前置き

by trapezoid | December 17, 2019
software-architecture | #software-architecture #game

この記事は DeNA Advent Calendar 2019 の12/18(水)の記事です。

@Trapezoid こと大竹悠人です。普段はDeNAでUnity製ゲーム向けの共通基盤を作る仕事をしています。

DeNAのモバイルゲーム開発では、サーバー/クライント間の連携手法に関して一般的な作りかたからかなり離れた手法を用いています。

今回は、それについてざっくりと解説してみようと思います。

なお、今回の内容はGame Developers Meeting(GDM) Vol.39 エンジニア向け勉強会で発表する内容の前置き部分とも言える内容になっています。

この記事を見て興味を持った方は是非(この記事が公開される頃には残念ながら参加締め切りが過ぎてしまっているのですが…)GDMに参加するか、発表後に公開予定の資料を見ていただけると幸いです。

一般的なモバイルゲームのつくりかた

一般的なモバイルゲームでは、以下のようなアーキテクチャが主流です。

  • クライアントは場面に応じた種類のサーバーのAPIを呼び出す
    • サーバーが持つ情報を必要に応じて取得する
  • 得られた情報に基づいてクライアントがゲームを進行する
    • バトルや、バトル外のUIなど
  • 進行に応じてプレイヤーデータに変更を加える場合には、その内容に応じた種類のサーバーのAPIを進行に応じたパラメータを付けて呼び出す

このような作りの場合、クライアントはユーザーからのインタラクティブな操作を受け持ち、プレイヤーデータを直接改変する権利はサーバーにしかありません。

ブラウザでのモバイルゲーム開発の時代から面々と続く、かなり枯れたアーキテクチャです。

メリットとしては、

  • サーバー側にでプレイヤーデータの変更を行うので、ユーザーの手元でのデータの改変が難しい
    • チート対策になる
  • モバイルゲームによくある非同期なプレイヤー間連携機能を、サーバー側で自由に実装することで、クライアントからその複雑さを隠蔽できる
    • サーバーでAPIを実装して、クライアントはそれを呼ぶだけで複雑なイベントなども実現できる
  • 多くのエンジニアに馴染みがある

などがありますが、一方でデメリットとして

  • サーバーとクライアントの実装の分断が発生する
    • 実装言語もパラダイムも違うので、設計やチームが分断するポイントになってしまう
    • どこまでサーバーでやるか?という判断が人ごとにわかれがち
    • 不必要な車輪の再発明をしてしまうことも
    • 社内でもチームごとにノウハウが散らばりがち

というのがあるかと思います。

サーバー”コード”レスアーキテクチャ

DeNAのモバイルゲーム開発では、Unity, Cocos2d-xなどによる非ブラウザのネイティブアプリ時代になってから、このような一般的な作りにとらわれない手法でのモバイルゲーム開発を実践しています。

このアーキテクチャは、ざっくりと言えば以下のようなものです

  • クライアントはサーバーからプレイヤーデータそのものをを取得する
  • プレイヤーデータに基づいてクライアントがゲームを進行する
  • 進行に応じてプレイヤーデータに変更を加える場合には、プレイヤーが更新後のプレイヤーデータそのものを生成し、その内容をサーバー側にAPIを通じて保存する
  • サーバー側はプレイヤーデータの詳細を知らず、必要とされる共通機能を提供する

近年注目されてきているゲーム用mBaaSである、PlayFabやGameSparks,Game Server Services(GS2)などをイメージすると近いものがあるかと思います。

大きな違いは、ゲーム用mBaaSがサーバー側にある機能が広範になり、サーバー側にトリガや設定を詰め込んでいく傾向にある一方で、このアーキテクチャではゲームクライアント側に処理を寄せることをむしろ推奨しています。

クライアントを実装するチームからすると、ほとんどサーバーコードを知ることなく、SDKを扱うだけでモバイルゲームを開発することが出来るという開発スタイルになります。

このことから、最近大竹がサーバー”コード”レスアーキテクチャという呼び方を社内で広めています。(まだあまり定着していませんが、単にmBaaSと呼ぶより趣旨が分かりやすいんじゃないかと大竹は信じています…)

サーバー”コード”レスとは言いつつ、クライアントで出来たほうがシンプルなことはクライアントで、サーバーで出来たことがシンプルなことはサーバーで実現できるのが、このアーキテクチャの目指すところです。このあたりについては、DeNAのネイティブアプリにおけるサーバ開発の現在と未来に詳細が語られています。

サーバー側のプラットフォームでやっていることとその進化は、これまで幾度も対外的にも発表されていきているので、詳細は割愛します。(リンク先をご一読下さい)

クライアントを作るときの課題

このアーキテクチャを実践するには、クライアント側に多くの処理を持ってくることになります。

このために、通常のアーキテクチャでの実装と比較して、様々なことに気を配る必要が出てきます。

  1. プレイヤーデータのテーブル設計
  2. プレイヤーデータの一貫性の保証
  3. プレイヤーデータを扱うドメインロジックのレイヤー設計
  4. プレイヤーデータのチート対策
  5. 時刻の正確性の保証

DeNAでは、D4Lという内製ライブラリによってこれらを楽に解決できるようにしています。

それぞれの詳細と解決方法について語りたいところなのですが、あまりに話が長くなるので本日はここまでで許して下さい…

続きはGDM(と、その発表資料)で!