「スマホゲームみたいな運用型のゲームを作ってみたい!」、「オンライン対戦ゲームを作ってみたい!」
でも、いざ調べてみると「API」「JSON」「エンドポイント」など、聞き慣れない用語がたくさん出てきて、戸惑った人もいるのではないでしょうか?
元々システム開発に馴染みのある人であれば当たり前かもしれませんが、ゲーム開発をキッカケにシステムに触れた人にとってみると、サーバや通信周りは用語や覚えることが多く、最初はとても戸惑うことが多いと思います。
運用型ライブゲームを作るには、買い切りゲームとは違ったアプローチが必要です。
プレイヤーのデータをサーバで管理し、リアルタイムでコンテンツを配信する仕組みを理解する必要があります。
今回は「運用型ライブゲームを作るために必要な知識」を軸に、その過程で必ず出てくる重要な概念や用語について、ゲーム開発者向けに基礎から分かりやすく解説していきます!
運用型ライブゲームとは?
買い切りゲームVS 運用型ライブゲーム
買い切りゲーム
- 一度購入したら、そのままずっと遊べる
- アップデートは基本的に無し(あってもバグ修正程度)
- データはすべて端末内に保存
運用型ライブゲーム
- 継続的にコンテンツが追加される
- イベント、ガチャ、ランキングなどリアルタイム要素
- データの一部をサーバで管理
なぜサーバが必要なのか?
運用型ライブゲームでは、サーバが必須です。
なぜなら、複数のユーザのデータを統合的にサーバで扱う必要があるからです。
たとえば、100人のユーザがランキングを競うとします。その場合、100人のランクを誰が管理すべきか?
それはサーバで行うしかないのです。
他にも、サーバを使って以下のようなことを運用型ゲームでは行います。
リアルタイム性
- 全プレイヤー共通のイベント開催
- ランキングの更新
- 他プレイヤーとの協力・対戦
データの永続化
- 機種変更時のデータ引き継ぎ
- チート対策(重要なデータはサーバで管理)
- 複数端末でのプレイ
継続的なコンテンツ配信
- 新キャラクター、新ステージの追加
- バランス調整
- 期間限定イベント
この記事では、中央集権的にデータを管理する先をサーバ、Unityで作った各種端末でのアプリーケーションをクライアントと呼称しています。

ライブゲームの設計
サーバとクライアントの役割分担
ライブゲーム開発では、「どの処理をサーバーで行い、どの処理をクライアント(ゲームアプリ)で行うか」を適切に分ける必要があります。
たとえば、以下のような処理はサーバ側で行うべきです。
ゲームデータの管理
- プレイヤーのレベル、経験値、所持アイテム、通貨(ゲーム内コイン)などのセーブデータの保持
チート対策が必要な処理
- ガチャの抽選結果
- バトルの勝敗判定
- 報酬の付与
他プレイヤーとの共有データ
- ランキング・スコア
- ギルド・フレンド機能
- マルチプレイのマッチング
ゲーム設定・マスターデータ
- キャラクターのステータス設定
- ステージの難易度設定
- イベントの開催期間
クライアント(ゲームアプリ)側で処理すべきこと
クライアント側ではサーバで行う以外の処理を実装します。
表示・演出関連
- UI・メニューの表示
- アニメーション・エフェクト
- サウンド再生
ゲーム内の処理
- キャラクターの移動
- 簡単な当たり判定
- 一時的な計算
設計をするときには、「チートされたら困るもの」、「複数のユーザで共有するもの」、「端末などをまたいで引き継ぐもの」などがサーバ側で処理すべき内容です。
何をサーバ側で処理し、何をクライアント側で処理すべきかを適切に切り分けることが設計において最重要とも言えます。
サーバを含めた実装の流れ
ここまで読んだ人はこう疑問に思うかもしれません。
「サーバ側で処理をするというけど、実際サーバ側でどうやって処理をして、Unityで作ったゲームに情報を渡すの?」
この疑問を、
【1】クライアントとサーバとの通信の流れ
【2】サーバ側の実装方法
【3】クライアント側の実装方法
に分けて解説します。
【1】クライアントとサーバとの通信の流れ
まず、通信のやり取りにおいて知っておくべき最重要ワードがあります。
それは、
リクエスト
レスポンス
です。
リクエストとは、サーバ側にお願いする通信のことです。
たとえば、ゲーム側でスコア9000点を取れたらからランキングに9000点で登録してくれ~というお願いを投げることを「リクエスト」といいます。
一方、「レスポンス」とは、サーバ側から受け取ったリクエストに対して、「成功したよ」なのか、「サーバエラーで処理出来なかったよ」といったそのリクエストの結果を情報として返します。

クライアント側から「リクエスト」を投げて、サーバ側で「レスポンス」を返す、これが基本の流れです。
この流れを念頭に置いておきましょう。
【2】サーバ側の実装方法
では、実際にサーバにリクエストを投げ、サーバがレスポンスを返すようになるためには何をすればいいのでしょう?
以下のStepに分けて解説します。
(1) サーバと言語の選定
(2) 実装
サーバ側の実装 - サーバと言語の選定 -
サーバがクライアントからレスポンスを受け取るには、まずサーバ側の処理を実装する必要があります。
現代だと、AWSやGoogleCloudRunなどのクラウドサーバーが主流(ゲーム業界だとAWSが主流と聞きます)ですので、基本的に実装する場合はクラウドサーバを使うことになるでしょう。(一応、自宅のPCを24時間起動してサーバにする、といったことも出来はします)
クラウドサーバサービスでは、世界中のあらゆるところにサーバを保持しています。
そのため、クライアントの存在する地域と近い地域にあるサーバを利用することが出来ます。
たとえば、アメリカからの通信を日本サーバを介してレスポンスすると、どうしても時間が掛かってしまうため、アメリカからの通信はアメリカのサーバで処理をすべきです。
こうしたサーバの置いてある地域のことを「リージョン」といいます。

また、クラウドサービスが提供しているのはあくまで、どのリージョンにどういう設定でサーバを稼働させるか、というところまでで、サーバにどんな処理をさせるかは開発者自身がコードを書いて実装する必要があります。
UnityはC#でしか実装出来ませんが、サーバの実装言語はUnityに比べて多くの選択肢があります。
よく使われている言語だと、以下の通りです。
・Node.js(JavaScript)
・Python
・Ruby
初心者にオススメなのは、Node.jsです。Javascriptベースなので、Webのフロントエンド開発で使うJavascriptがサーバ開発でも使えるので、学習コストが低いからです。
また、後述するサーバサイドのサービスは、Javascript(もしくはJavascriptの応用版のTypeScript)には基本的に対応しているので、どの言語にも馴染がなければNode.jsが良いでしょう。
サーバ側の実装 -実装-
どの言語で開発をするかを決めたら次は実装です。
実装するためには「API」を決める必要があります。
APIとは、サーバとの通信をやり取りするための規格のことです。
具体的には、
・どのURLに(エンドポイント)
・どんな形式でリクエストを投げて
・どんな形式でレスポンスを返す
の取り決めです。

サーバ側では、どんなエンドポイントを公開し、リクエストを受け取ったらどのような処理を行うのかを、サーバ側の実装言語を使って実装し、公開します。
サーバ側で実装した内容を公開する作業を「デプロイ」と言います。
サーバ側の実装は詳しく書くとキリがないので、今回はここまでにしておきますが、カンタンにまとめると、サーバ側の言語でサーバにAPIの実装を行ってデプロイする、というのがサーバ側の実装作業です。
【3】クライアント側の実装方法
サーバ側が実装出来たら、先程のAPIの取り決めとおり、エンドポイントのURLに、リクエストを送る必要があります。
リクエストを送る時に一番重要になってくるのが、
JSON(JavaScript Object Notation)
というデータフォーマットです。
たとえば、以下のようなフォーマットで定義されているデータがJSONフォーマットです。
{
"playerId": 12345,
"playerName": "勇者太郎",
"level": 25,
"hp": 850,
"mp": 320,
"inventory": [
"ひのきのぼう",
"やくそう",
"まほうのつるぎ"
],
"isOnline": true
}
これは通信を行うときにはみんなこのフォーマットで送ろうねという規格のことで、世界共通でこのフォーマットが使われています。
サーバにデータを送るために、UnityのデータをJSON形式に変換して、エンドポイントのURLにリクエストを送信する、というのがクライアント側で行う基本の処理です。
そのため、クライアント側では、C#などで定義されているデータをJSONに変換し、Webリクエストを投げる必要があります。
たとえば、以下のようなコードで実装出来ます。
(1)PlayerクラスをJSONに変換するコード
using UnityEngine;
using Newtonsoft.Json;
public class SimplePlayerJson : MonoBehaviour
{
// Playerクラス定義
[System.Serializable]
public class Player
{
public string Name;
public int HP;
}
void Start()
{
TestPlayerJson();
}
void TestPlayerJson()
{
// 1. Playerオブジェクト作成
Player player = new Player();
player.Name = "勇者太郎";
player.HP = 100;
// 2. オブジェクト → JSON変換
string json = PlayerToJson(player);
}
// PlayerオブジェクトをJSONに変換
public string PlayerToJson(Player player)
{
return JsonConvert.SerializeObject(player);
}
}
JSONへの変換は、Unity標準で入っている、Newtonsoftというライブラリを使うことで非常にカンタンに実装が出来ます。独自のクラスで定義した内容もJSONに変換してくれる強力なライブラリです。
(2)APIを呼び出す
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
public class JSONSender : MonoBehaviour
{
// JSONを指定したURLに送信するメソッド
public void SendJSON(string json, string endpointURL)
{
StartCoroutine(SendJSONCoroutine(json, endpointURL));
}
IEnumerator SendJSONCoroutine(string json, string url)
{
// POSTリクエストを作成
UnityWebRequest request = UnityWebRequest.Post(url, json);
request.SetRequestHeader("Content-Type", "application/json");
// サーバーに送信
yield return request.SendWebRequest();
// 結果を確認
if (request.result == UnityWebRequest.Result.Success)
{
Debug.Log("送信成功!");
}
else
{
Debug.Log("送信失敗: " + request.error);
}
}
}
Web通信を行う場合は、UnityWebRequestを使うのが一般的です。UnityWebRequest.Post(url, json)
とありますが、このurlがエンドポイント、jsonが変換したJSONデータのことです。
送る内容が「セーブデータ」であったり、「ユーザスコア」であったり、「ログイン記録」であったり。
サーバ側のAPIに合わせて対応するJSONデータを作って、サーバに送るというのがクライアント側で実装する内容です。
また、例えばガチャの当選結果をサーバ側で処理をする場合、クライアント側は、「ガチャを回す」というリクエストを投げ、サーバ側でのレスポンスで「ガチャ結果」を返して、Unity側で画面表示を行う、といった流れになります。
基本的に、確率をいじられて欲しくないようなデータはサーバ側で処理をするべきです。
クライアント側のデータは、改ざんされる可能性があります。
たとえば、クライアント側でガチャ結果を決定してサーバに送る方式の場合、サーバに送るデータ内容を改ざん(書き換え)して送られてしまうリスクがつきまといます。
運営型ゲームの場合、不正ユーザや改ざんなどが発生するととたんにユーザ数の減少につながる部分も大きいので、改ざんされないような仕組みをあらかじめ考えて設計する必要があります。
サーバ通信を含む開発の勘所
今回の記事は初心者向けの触りの記事なので深い部分までは書きませんが、サーバ通信を含む開発では、通常のゲームとはまた違った実装の考慮点が発生します。
サーバとの通信費を抑える工夫
クラウドサービスを使ってサーバを実装する場合、サーバの利用費用が発生します。
基本的にクラウドサービスは従量課金のため、ユーザ数が増えるほどサーバ代は増えます。極端な例ですが、ユーザが落としてくれるお金よりもサーバ通信費が多くなれば、遊ばれるほど赤字になってしまいます。
また、サーバとの通信は遅延を挟むため、ユーザ体験としても、お金的な面でも極力通信量は極力減らす必要があります。
APIで送る内容を出来るだけまとめたり、毎分通信を行うような処理は無くしたりなど、通信数を減らすことを念頭に置いた設計が必要です。
非同期処理と通信のエラーハンドリング
通信が絡む処理では、ローカルだけのゲーム開発と比べ、エラーハンドリングを重点的に行う必要があります。
これは、クライアント側で問題がなくても、サーバ側で問題が生じたり、クライアント側のネットワークが不安定になることでレスポンスが正しく返ってこないといった不測の自体が多く発生するからです。
そのため、一般的にネットワークを挟む処理の場合、非同期で処理を実行し、レスポンスが正しく返ってきたら処理を抜けるが、レスポンスがErrorで返ってきたらError画面を表示する、といった対応を取る必要があります。
非同期処理については、UniTaskを使うのがオススメです。コルーチンではこういった通信周りの実装をするとこんがらがって訳わかんなくなります。
また、エラーハンドリングについては、try ~ catch構文を使って、例外をハンドリングするといった実装をするのがよいでしょう。
サードパーティ製サーバサイドサービスの活用
ここまで読んだ方はこう思うかもしれません。
「サーバサイドは覚えること多すぎて無理無理の助~!!」
そんな人のために、サーバサイドの知識が少ない人でもサーバサイドを実装できるサービスが世の中にはいくつかあります。代表的なサービスを紹介しておきます。
PlayFab(Microsoft)
特徴:
- ゲーム専用のBaaS(Backend as a Service)
- 無料枠が充実している(月間10万ユーザまで無料)
- Unity専用SDKあり
できること:
- プレイヤー認証・管理
- セーブデータ保存
- ランキング・リーダーボード
- アイテム・通貨管理
- プッシュ通知
MicroSoftに買収された経緯があるためMicroSoftのサービスとの連携が非常に充実しています。
カンタンなランキングサービスを使うだけであれば、オススメのサービスです。
私が公開しているライブラリを使えばランキング機能だけであればすぐに作れると思います。

ただ、個人的感想としては、ユーザの分析や一覧での出力、ダッシュボードの機能などは、Azureへの連携を前提としている箇所があり、結構取り回しが悪いと感じることがあります。
GameServerServices(GS2)

特徴:
- 過去12か月間の売上高の合計が1000万円未満の個人または法人は利用無料
- UnitySDKあり
できること:
- プレイヤー認証(Unity Authentication)
- クエスト機能
- ログインボーナス
- ミッション
- プレゼントボックス
などなど。
元任天堂のエンジニアが作っているサービスなので、非常に日本ファーストなサービスらしいですが、筆者はまだ試せていません。
Firebase(Google)
特徴:
- Googleが提供するモバイルアプリ開発プラットフォーム
- 豊富な機能とドキュメント
- 他のGoogle サービスとの連携
- UnitySDKあり
できること:
- リアルタイムデータベース
- ユーザー認証
- プッシュ通知
- アナリティクス
- A/Bテスト
こんなゲームにおすすめ:
- リアルタイム性が重要なゲーム
- 詳細なデータ分析が必要
- Google系サービスと連携したい
まとめ
以上、運用型ライブゲーム開発で知っておくべき基礎知識でした。長期的に運用していくゲームであれば、サーバ側の知識は必須です。
Unityとサーバサイド両方の知識を組み合わせてより良いゲームを作っていきましょう!
それでは、素敵なゲーム制作ライフを!
コメント