NAV
Unity Unreal Engine 4

Game Server Services

Game Server Services(GS2) とはモバイルゲーム開発に特化したバックエンドサーバサービス(BaaS)です。

ゲーム開発に必要なネットワーク機能をコンポーネント化してサービスとして提供します。 ゲーム内から必要な一部のコンポーネント単位で利用することができるよう設計されており、手軽に・手頃な価格で・高性能なサーバ機能を利用できます。

利用料金

Individual プラン

過去12か月間の売上高が1000万円未満の法人または個人は全ての機能を無料で使用できます。 (GS2を利用するゲームによる売り上げではなく、他の事業の売り上げも含みます)

月の平均リクエスト回数が秒間10回または、一定期間継続して秒間リクエスト回数が100回を超える場合はその限りではありません。 またその際もアプリケーションの改修に必要な時間は考慮しますが、速やかに対応ください。

Professional プラン

過去12か月間の売上高が1000万円以上の場合はこちらの料金に基づきます。

一般的な利用料金

サービス内に特別な記載がない限り、以下の料金でサービスを利用できます。

無料枠

2万円を超過するまでは無料でご利用いただけます。 2万円を超過すると超過分のみではなく、全利用額の請求が発生します。

Enterprise プラン

MAUあたり30円~150円(ゲームがサーバに依存している程度によって決定)の固定額で全ての機能を使用できます。 実際の利用料金請求時には Professional プランの利用料金と比較して”安いほう”で請求が行われます。

利用をご希望の際は GS2 にご相談ください。

処理性能

GS2 はゲームサーバを性能を気にすることなく利用いただけるよう設計されています。 リリース前のベンチマークで秒間10万回のアクセスを処理できることを確認しています。

しかし、すべてのAPIを性能を気にする必要なく提供することは困難であり、 一部のAPIには性能を保証するラインを別途設けている場合があります。 個別の性能保証が定義されている場合は各コンポーネントで定義しています。

はじめかた

はじめに

この章では、Unity のプロジェクトを作成して GS2 の機能を利用するために必要な 1. GS2のウェブサイト側の手順と 2. Unity上のSDK組み込み

までをまとめています。 ネットワークを利用したアカウント管理やアイテム課金、プッシュ通知などをUnityのゲームに初めて組み込む人はじっくりと、他のサービスを触ったことがある人は飛ばしながら確認してください。

ウェブサイト上でGS2 アカウントの作成

まず、 GS2 のサイト からGS2開発用アカウントの登録を行ってください。 GS2開発用アカウント登録は、ゲームの開発管理者が行います。

GS2では主にブラウザ上で動くマネージメントコンソールを使ってプロジェクトを管理します。 複数人で同一プロジェクトを管理したい場合はサービス紹介のGS2-Identifierをご確認ください。

ウェブサイト上でGS2プロジェクトの作成

GS2 のアカウントを作成後、最初にするべきことは GS2サービス上で対象となるゲーム(以下 プロジェクト と呼びます)を作成することです。

プロジェクト とはゲームタイトルと 1:1 となる概念です。 GS2 のあらゆるリソースは プロジェクト に関連付けて保持され、他の プロジェクト のデータには基本的に干渉できません。

もちろん、新規のゲームタイトルを作り始める時に最初にGS2のプロジェクト設定をしても良いですし、すでに開発中のタイトルにGS2を追加することもできます。

プロジェクト名は 英数字大文字小文字とハイフン、アンダーバー で構成することが出来ます。(例:MySuperCool_Stg_Game-001) 日本語のプロジェクト名は設定できません。

クレデンシャルの発行

GS2 の API を利用するには認証情報(以下 クレデンシャル 、と呼びます)が必要です。

クレデンシャルユーザ の認証に用いる情報で、 GS2 のサービス利用に関わる権限はこの ユーザ 単位で管理されます。 権限の詳細は セキュリティポリシー に定義され、これを ユーザ に割り当てて使用します。

権限管理にまつわるリソースは、以下の階層構造で管理されています。

セキュリティポリシーの例

{
  "Version": "2016-04-01",
  "Statements": [
    {
      "Effect": "Allow",
      "Actions": [
        "Gs2Account:CreateAccount"
      ],
      "Resources": [
        "*"
      ]
    }
  ]
}

個々の API の呼出可否は セキュリティポリシー に定義されます。 セキュリティポリシー は JSON形式で記述します。

GS2 では開発者向けに2種類の セキュリティポリシー を事前に定義して提供しています。 あらゆるAPIを呼び出せる AdministratorAccess と、ゲーム内に組み込んで使用する想定の ApplicationAccess です。 後者はチート行為につながるような操作ができるAPIを呼び出すことができないよう設定されています。

セキュリティポリシー の詳細は別途 セキュリティポリシーのフォーマット を参照してください。

GS2-Deploy による設定

クレデンシャルの発行に必要な設定は GS2-Identifier の管理画面からも個別に登録できますが、 GS2-Deploy を利用した設定が便利です。

GS2-Deploy は GS2 上で継続的デリバリーを実現するためのサービスです。 GS2に対して設定したい項目を テンプレート として yaml 形式で記述し、 GS2-Deploy に登録することで設定を反映できます。

その際に作成することになるエンティティが スタック です。 テンプレート を指定した スタック を作成することで、 テンプレート に記述した設定が反映されます。 また、 スタック に対して変更した テンプレート を再適用した場合も、変更点を自動的に検出し、作成が必要なリソースは作成、更新が必要なリソースは更新、削除が必要なリソースは削除します。

これによって開発者は、いらなくなったリソースを削除するなどのオペレーションを行うことなく、求める状況を宣言的に テンプレート に記述するだけでよくなります。

では、さっそく テンプレート を使って GS2-Deploy でスタックを作成してみましょう。

クレデンシャルを発行する GS2-Deploy テンプレートの例

GS2TemplateFormatVersion: "2019-05-01"
Description: GS2 SDK identifier template Version 2019-07-10

Globals:
  Alias:
    ApplicationUserName: application

Resources:
  IdentifierApplicationUser:
    Type: GS2::Identifier::User
    Properties:
      Name: ${ApplicationUserName}

  IdentifierApplicationUserAttachPolicy:
    Type: GS2::Identifier::AttachSecurityPolicy
    Properties:
      UserName: ${ApplicationUserName}
      SecurityPolicyId: grn:gs2::system:identifier:securityPolicy:ApplicationAccess
    DependsOn:
      - IdentifierApplicationUser

  IdentifierApplicationIdentifier:
    Type: GS2::Identifier::Identifier
    Properties:
      UserName: ${ApplicationUserName}
    DependsOn:
      - IdentifierApplicationUser

Outputs:
  ApplicationClientId: !GetAttr IdentifierApplicationIdentifier.Item.ClientId
  ApplicationClientSecret: !GetAttr IdentifierApplicationIdentifier.ClientSecret

隣に示したのは、 ApplicationAccess 権限を設定したユーザを作成する テンプレート のサンプルです。 ApplicationUserName: application の部分を変更すると、GS2-Identifier に作成されるユーザ名を変更できます。

テンプレートをダウンロード

この テンプレート をファイルに保存し、 GS2-Deploy の スタックの新規作成テンプレートデータ に指定してスタックを作成します。

作成したスタックに登録された設定の反映状態は、スタックの 実行状態 の項目で確認できます。 数秒〜数分後には CREATE_COMPLETE になり、 クレデンシャル の設定が完了しているはずです。

反映完了後に アウトプット タブを選択すると、クレデンシャルの クライアントIDクライアントシークレット が表示されます。 この値は後ほど SDK に設定しますので、確認できる場所を覚えておいてください。

GS2-SDK for Game Engine のダウンロードと導入

GS2-SDK for Game Engine から GS2-SDK for Unity もしくは GS2-SDK for Game Engine を入手できます。 お使いの環境にあったパッケージをダウンロードし、示された手順に従って導入してください。

これでゲームエンジンから GS2 を利用するための準備が整いました。

アカウント管理機能の実装サンプル

テンプレート

GS2-Account の利用を開始するためのテンプレート例

GS2TemplateFormatVersion: "2019-05-01"
Description: GS2-Account initialize template Version 2010-06-26

Globals:
  Alias:
    AccountNamespaceName: game-0001
    KeyNamespaceAccountAuthentication: account-encryption-key-namespace
    KeyAccountAuthentication: account-encryption-key

Resources:
  KeyNamespaceAccountAuthentication:
    Type: GS2::Key::Namespace
    Properties:
      Name: ${KeyNamespaceAccountAuthentication}

  KeyAccountAuthentication:
    Type: GS2::Key::Key
    Properties:
      NamespaceName: ${KeyNamespaceAccountAuthentication}
      Name: ${KeyAccountAuthentication}
    DependsOn:
      - KeyNamespaceAccountAuthentication

  AccountNamespace:
    Type: GS2::Account::Namespace
    Properties:
      Name: ${AccountNamespaceName}

Outputs:
  AccountNamespaceName: !GetAttr AccountNamespace.Item.Name
  KeyAccountAuthenticationKeyId: !GetAttr KeyAccountAuthentication.Item.KeyId

まず、サンプルコードから利用する GS2-Account の設定を行います。 GS2-Deploy の スタックの新規作成 で、以下のテンプレートを テンプレートデータ に指定してスタックを作成します。

テンプレートをダウンロード

サンプルコード

サンプルコード

using System;
using System.Collections;
using System.Collections.Generic;
using Gs2.Core;
using Gs2.Unity.Gs2Account.Model;
using Gs2.Unity.Gs2Account.Result;
using Gs2.Unity.Util;
using UnityEngine;

public class Gs2AccountSample2 : MonoBehaviour
{
    // GS2-Identifier で発行したクライアントID
    public string clientId;

    // GS2-Identifier で発行したクライアントシークレット
    public string clientSecret;

    // アカウントを作成する GS2-Account のネームスペース名
    public string accountNamespaceName;

    // アカウントの認証結果に付与する署名を計算するのに使用する暗号鍵
    public string accountEncryptionKeyId;

    void Start()
    {
        StartCoroutine(CreateAndLoginAction());
    }

    public IEnumerator CreateAndLoginAction()
    {
        // GS2 SDK のクライアントを初期化

        Debug.Log("GS2 SDK のクライアントを初期化");

        var profile = new Gs2.Unity.Util.Profile(
            clientId: clientId,
            clientSecret: clientSecret,
            reopener: new Gs2BasicReopener()
        );

        {
            AsyncResult<object> asyncResult = null;

            var current = profile.Initialize(
                r => { asyncResult = r; }
            );

            yield return current;

            // コルーチンの実行が終了した時点で、コールバックは必ず呼ばれています

            // クライアントの初期化に失敗した場合は終了
            if (asyncResult.Error != null)
            {
                OnError(asyncResult.Error);
                yield break;
            }
        }

        var gs2 = new Gs2.Unity.Client(profile);

        // アカウントを新規作成

        Debug.Log("アカウントを新規作成");

        EzAccount account = null;

        {
            AsyncResult<EzCreateResult> asyncResult = null;

            var current = gs2.Account.Create(
                r => { asyncResult = r; },
                accountNamespaceName
            );

            yield return current;

            // コルーチンの実行が終了した時点で、コールバックは必ず呼ばれています

            // アカウントが作成できなかった場合は終了
            if (asyncResult.Error != null)
            {
                OnError(asyncResult.Error);
                yield break;
            }

            // 作成したアカウント情報を取得
            account = asyncResult.Result.Item;
        }

        // ログイン

        Debug.Log("ログイン");

        GameSession session = null;

        {
            AsyncResult<GameSession> asyncResult = null;
            var current = profile.Login(
               authenticator: new Gs2AccountAuthenticator(
                   session: profile.Gs2Session,
                   accountNamespaceName: accountNamespaceName,
                   keyId: accountEncryptionKeyId,
                   userId: account.UserId,
                   password: account.Password
               ),
               r => { asyncResult = r; }
           );

            yield return current;

            // コルーチンの実行が終了した時点で、コールバックは必ず呼ばれています

            // ゲームセッションオブジェクトが作成できなかった場合は終了
            if (asyncResult.Error != null)
            {
                OnError(asyncResult.Error);
                yield break;
            }

            // ログイン状態を表すゲームセッションオブジェクトを取得
            session = asyncResult.Result;
        }

        // 引き継ぎ情報の一覧を取得

        Debug.Log("引き継ぎ情報の一覧を取得");

        {
            AsyncResult<EzListTakeOverSettingsResult> asyncResult = null;

            var current = gs2.Account.ListTakeOverSettings(
                r => { asyncResult = r; },
                session,
                accountNamespaceName
            );

            yield return current;

            // コルーチンの実行が終了した時点で、コールバックは必ず呼ばれています

            // APIの呼び出しが完了したら通知されるコールバック
            if (asyncResult.Error != null)
            {
                OnError(asyncResult.Error);
                yield break;
            }

            List<EzTakeOver> items = asyncResult.Result.Items;
            foreach (var item in items)
            {
                // 引き継ぎに関する情報が取得される
            }
        }

        // GS2 SDK の終了処理

        Debug.Log("GS2 SDK の終了処理");

        {
            // ゲームを終了するときなどに呼び出してください。
            // 頻繁に呼び出すことは想定していません。
            var current = profile.Finalize();

            yield return current;
        }
    }

    private void OnError(Exception e)
    {
        Debug.Log(e.ToString());
    }
}
// MyActor.hpp

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include <gs2/ez/Gs2Ez.hpp>
#include <memory>
#include "MyActor.generated.h"

UCLASS()
class GS2SDKAPP_API AMyActor : public AActor
{
    GENERATED_BODY()

public:
    // Sets default values for this actor's properties
    AMyActor();

    // GS2-Identifier で発行したクライアントID
    UPROPERTY(EditAnywhere, Category = "GS2")
    FString ClientId;

    // GS2-Identifier で発行したクライアントシークレット
    UPROPERTY(EditAnywhere, Category = "GS2")
    FString ClientSecret;

    // アカウントを作成する GS2-Account のネームスペース名
    UPROPERTY(EditAnywhere, Category = "GS2")
    FString AccountNamespaceName;

    // アカウントの認証結果に付与する署名を計算するのに使用する暗号鍵
    UPROPERTY(EditAnywhere, Category = "GS2")
    FString AccountEncryptionKeyId;

private:
    std::shared_ptr<gs2::ez::Profile> ProfilePtr;
    std::shared_ptr<gs2::ez::Client> ClientPtr;

    gs2::ez::GameSession GameSession;
    gs2::ez::account::EzAccount EzAccount;

    void ProfileInitialize();
    void AccountCreate();
    void ProfileLogin();
    void AccountListTakeOverSettings();
    void ProfileFinalize();

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

public:
    // Called every frame
    virtual void Tick(float DeltaTime) override;
};
// MyActor.cpp

#include "MyActor.h"
#include "Engine.h"

// Sets default values
AMyActor::AMyActor()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
    Super::BeginPlay();

    ProfileInitialize();
}

void AMyActor::ProfileInitialize()
{
    // GS2 SDK のクライアントを初期化

    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, "profile.initialize");

    ProfilePtr = std::make_shared<gs2::ez::Profile>(
        TCHAR_TO_ANSI(*ClientId),
        TCHAR_TO_ANSI(*ClientSecret),
        gs2::ez::Gs2BasicReopener()
        );

    ClientPtr = std::make_shared<gs2::ez::Client>(
        *ProfilePtr
        );

    ProfilePtr->initialize(
        [this](gs2::ez::Profile::AsyncInitializeResult r)
        {
            if (r.getError())
            {
                // クライアントの初期化に失敗した場合は終了
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "profile.initialize failed.");
            }
            else
            {
                AccountCreate();
            }
        }
    );
}

void AMyActor::AccountCreate()
{
    // アカウントを新規作成

    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, "account.create");

    ClientPtr->account.create(
        [this](gs2::ez::account::AsyncEzCreateResult r)
        {
            if (r.getError())
            {
                // アカウントが作成できなかった場合は終了
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "account.create failed.");
            }
            else
            {
                // 作成したアカウント情報を取得
                EzAccount = r.getResult()->getItem();

                ProfileLogin();
            }
        },
        TCHAR_TO_ANSI(*AccountNamespaceName)
    );
}

void AMyActor::ProfileLogin()
{
    // ログイン

    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, "profile.login");

    ProfilePtr->login(
        [this](gs2::ez::Profile::AsyncLoginResult r)
        {
            if (r.getError())
            {
                // ゲームセッションオブジェクトが作成できなかった場合は終了
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "profile.login failed.");
            }
            else
            {
                // ログイン状態を表すゲームセッションオブジェクトを取得
                GameSession = *r.getResult();

                AccountListTakeOverSettings();
            }
        },
        gs2::ez::Gs2AccountAuthenticator(
            ProfilePtr->getGs2Session(),
            TCHAR_TO_ANSI(*AccountNamespaceName),
            TCHAR_TO_ANSI(*AccountEncryptionKeyId),
            EzAccount.getUserId(),
            EzAccount.getPassword()
        )
    );
}

void AMyActor::AccountListTakeOverSettings()
{
    // 引き継ぎ情報の一覧を取得

    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, "account.listTakeOverSettings");

    ClientPtr->account.listTakeOverSettings(
        [this](gs2::ez::account::AsyncEzListTakeOverSettingsResult r)
        {
            if (r.getError())
            {
                // 引き継ぎ情報の一覧が取得できなかった場合は終了
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "account.listTakeOverSettings failed.");
            }
            else
            {
                auto& items = r.getResult()->getItems();
                for (auto i = 0; i < items.getCount(); ++i)
                {
                    // 引き継ぎに関する情報が取得される
                }

                ProfileFinalize();
            }
        },
        GameSession,
        TCHAR_TO_ANSI(*AccountNamespaceName)
    );
}

void AMyActor::ProfileFinalize()
{
    // GS2 SDK の終了処理

    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, "profile.finalize");

    // ゲームを終了するときなどに呼び出してください。
    // 頻繁に呼び出すことは想定していません。
    ProfilePtr->finalize(
        [this]()
        {
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, "successfull.");
        }
    );
}

// Called every frame
void AMyActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

}

まずはゲームオブジェクト全体のコードサンプルをコード欄に示します。

解説

SDKの初期化

SDKの初期化

var profile = new Gs2.Unity.Util.Profile(
    clientId: clientId,
    clientSecret: clientSecret,
    reopener: new Gs2BasicReopener()
);

{
    AsyncResult<object> asyncResult = null;

    var current = profile.Initialize(
        r => { asyncResult = r; }
    );

    yield return current;

    // コルーチンの実行が終了した時点で、コールバックは必ず呼ばれています

    // クライアントの初期化に失敗した場合は終了
    if (asyncResult.Error != null)
    {
        OnError(asyncResult.Error);
        yield break;
    }
}

var gs2 = new Gs2.Unity.Client(profile);
ProfilePtr = std::make_shared<gs2::ez::Profile>(
    TCHAR_TO_ANSI(*ClientId),
    TCHAR_TO_ANSI(*ClientSecret),
    gs2::ez::Gs2BasicReopener()
);

ClientPtr = std::make_shared<gs2::ez::Client>(
    *ProfilePtr
);

ProfilePtr->initialize(
    [this](gs2::ez::Profile::AsyncInitializeResult r)
    {
        if (r.getError())
        {
            // クライアントの初期化に失敗した場合は終了
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "profile.initialize failed.");
        }
        else
        {
            AccountCreate();
        }
    }
);

こちらは GS2 にアクセスするための設定をしています。 clientId clientSecret にはクレデンシャルを設定します。 具体的な設定値は、先程 GS2-Deploy のクレデンシャルを作成するテンプレートを使ってスタックを作成し、 ステータスが CREATE_COMPLETE になっていることを確認した上で、アウトプットタブで確認できる ApplicationClientId ApplicationClientSecret の内容を設定してください。

Account Namespace Name KeyAccountAuthenticationKeyId も同様にアカウント管理導入テンプレートのアウトプットタブの内容を設定してください。

reopener にはアクセストークンをリフレッシュするためのハンドラーを設定します。 特にこだわりがなければ Gs2BasicReopener を設定しておくことで、GS2 が推奨するリフレッシュロジックが適用されます。

アカウントの作成

アカウントの作成

EzAccount account = null;

{
    AsyncResult<EzCreateResult> asyncResult = null;

    var current = gs2.Account.Create(
        r => { asyncResult = r; },
        accountNamespaceName
    );

    yield return current;

    // コルーチンの実行が終了した時点で、コールバックは必ず呼ばれています

    // アカウントが作成できなかった場合は終了
    if (asyncResult.Error != null)
    {
        OnError(asyncResult.Error);
        yield break;
    }

    // 作成したアカウント情報を取得
    account = asyncResult.Result.Item;
}
ClientPtr->account.create(
    [this](gs2::ez::account::AsyncEzCreateResult r)
    {
        if (r.getError())
        {
            // アカウントが作成できなかった場合は終了
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "account.create failed.");
        }
        else
        {
            // 作成したアカウント情報を取得
            EzAccount = r.getResult()->getItem();

            ProfileLogin();
        }
    },
    TCHAR_TO_ANSI(*AccountNamespaceName)
);

ここではゲームプレイヤーを識別するためのアカウント情報の作成を行っています。 accountNamespaceName にはアカウント情報を記録するネームスペースを指定します。

テンプレートの アウトプット で確認できる AccountNamespaceName の値を設定します。

Create メソッドのコールバックは、アカウントの作成処理が完了したときに呼び出されます。 エラーが発生した場合は r.Error に例外オブジェクトが格納されており、成功したときには r.Result に結果が格納されています。

なお、このアカウントの作成は本来、アプリケーションの初回起動時に1回だけ行うべきものです。 実際のアプリケーションではこの応答の内容をローカルストレージに保存し、2回目以降はストレージから取得した値を使用してください。

ログイン

ログイン

GameSession session = null;

{
    AsyncResult<GameSession> asyncResult = null;

    var current = profile.Login(
        authenticator: new Gs2AccountAuthenticator(
            session: profile.Gs2Session,
            accountNamespaceName: accountNamespaceName,
            keyId: accountEncryptionKeyId,
            userId: account.UserId,
            password: account.Password
        ),
        r => { asyncResult = r; }
    );

    yield return current;

    // コルーチンの実行が終了した時点で、コールバックは必ず呼ばれています

    // ゲームセッションオブジェクトが作成できなかった場合は終了
    if (asyncResult.Error != null)
    {
        OnError(asyncResult.Error);
        yield break;
    }

    // ログイン状態を表すゲームセッションオブジェクトを取得
    session = asyncResult.Result;
}
ProfilePtr->login(
    [this](gs2::ez::Profile::AsyncLoginResult r)
    {
        if (r.getError())
        {
            // ゲームセッションオブジェクトが作成できなかった場合は終了
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "profile.login failed.");
        }
        else
        {
            // ログイン状態を表すゲームセッションオブジェクトを取得
            GameSession = *r.getResult();

            AccountListTakeOverSettings();
        }
    },
    gs2::ez::Gs2AccountAuthenticator(
        ProfilePtr->getGs2Session(),
        TCHAR_TO_ANSI(*AccountNamespaceName),
        TCHAR_TO_ANSI(*AccountEncryptionKeyId),
        EzAccount.getUserId(),
        EzAccount.getPassword()
    )
);

つづいて GS2 へのログイン処理です。 accountNamespaceName には作成したアカウントが存在するネームスペースを指定し、 keyId にはアカウントの認証結果に付与する署名を計算するのに使用する暗号鍵を指定します。 更に、 userId password には先程作成したアカウントのユーザIDとパスワードを指定します。

ログイン処理が完了するとコールバックが呼び出され、先ほどと同じように エラーが発生した場合は r.Error に例外オブジェクトが格納されており、成功したときには r.Result に結果が格納されています。

r.Result にはログイン状態を表現するための GameSession オブジェクトが返ってきます。 以降 GS2 の API を呼び出すときにログイン状態でなければ呼び出せないAPIの引数には GameSession を渡して使用することとなります。

ログイン状態でなければ呼び出せないAPIの呼び出し

ログイン状態でなければ呼び出せないAPIの呼び出し

{
    AsyncResult<EzListTakeOverSettingsResult> asyncResult = null;

    var current = gs2.Account.ListTakeOverSettings(
        r => { asyncResult = r; },
        session,
        accountNamespaceName
    );

    yield return current;

    // コルーチンの実行が終了した時点で、コールバックは必ず呼ばれています

    // APIの呼び出しが完了したら通知されるコールバック
    if (asyncResult.Error != null)
    {
        OnError(asyncResult.Error);
        yield break;
    }

    List<EzTakeOver> items = asyncResult.Result.Items;
    foreach (var item in items)
    {
        // 引き継ぎに関する情報が取得される
    }
}
ClientPtr->account.listTakeOverSettings(
    [this](gs2::ez::account::AsyncEzListTakeOverSettingsResult r)
    {
        if (r.getError())
        {
            // 引き継ぎ情報の一覧が取得できなかった場合は終了
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "account.listTakeOverSettings failed.");
        }
        else
        {
            auto& items = r.getResult()->getItems();
            for (auto i = 0; i < items.getCount(); ++i)
            {
                // 引き継ぎに関する情報が取得される
            }

            ProfileFinalize();
        }
    },
    GameSession,
    TCHAR_TO_ANSI(*AccountNamespaceName)
);

ログイン状態でなければ使用できないAPIの例として、引き継ぎ設定の一覧取得APIを示しています。 session に GameSession を渡して、ログイン中のゲームプレイヤーが設定している引き継ぎ設定の一覧を取得できます。

マスターデータの管理

用語の定義

用語 意味
モデルマスター 管理画面から更新するゲームプレイヤーごとに変わらないデータ
モデル ゲーム内から使用するゲームプレイヤーごとに変わらないデータ
プロパティ モデルをもとに作成したゲームプレイヤーごとに異なるデータ

アカウント管理では出てきませんでしたが、ゲームの構成要素の中には所持品やクエストなどゲームプレイヤーごとには変わらないデータがあります。 このようなデータをGS2では モデル と呼んでいます。そして、モデルをもとにゲームプレイヤーの所持するデータになったものを プロパティ と呼んでいます。

一般的にマスターデータと捉えられるのは GS2 においては モデル にあたるかとおもいますが、GS2 においては モデルマスター という概念が存在します。 モデル モデルマスター の違いは、データの内容としては基本的には一緒ですが、実際にゲームから使われる状態にあるかどうか。という違いがあります。

つまり、GS2 の管理画面上で編集できるデータは モデルマスター であり、それを実際にゲーム内から使用できる状態に変換すると モデル に変わります。 この変換工程が必要な理由は、 モデルマスター に対する変更を一括してゲーム内に反映するためです。 この工程がない場合、管理画面で少しずつデータを更新していく過程でゲーム内に半端なデータが反映されてしまうことになります。

マスターデータの作成

GS2-Deploy のテンプレートでのマスターデータ管理例

GS2TemplateFormatVersion: "2019-05-01"
Description: GS2 master data template Version 2010-06-26

Globals:
  Alias:
    NamespaceName: inventory

Resources:
  Namespace:
    Type: GS2::Inventory::Namespace
    Properties:
      Name: ${NamespaceName}

  NamespaceSettings:
    Type: GS2::Inventory::CurrentItemModelMaster
    Properties:
      NamespaceName: ${NamespaceName}
      Settings:  # ここから下のデータが本来はJSONで指定する部分ですが、yaml として記述して反映できます
        version: 2019-02-05
        inventoryModels:
          - name: item
            metadata: ITEM
            initialCapacity: 40
            maxCapacity: 60
            itemModels:
              - name: item-0001
                metadata: ITEM_0001
                maxCount: 99
                sortValue: 1
              - name: item-0002
                metadata: ITEM_0002
                maxCount: 99
                sortValue: 2
              - name: item-0003
                metadata: ITEM_0003
                maxCount: 99
                sortValue: 3
          - name: character
            metadata: CHARACTER
            initialCapacity: 30
            maxCapacity: 50
            itemModels:
             - name: character-0001
               metadata: CHARACTER_0001
               maxCount: 1
               sortValue: 1

    DependsOn:
      - Namespace

この変換工程は、すべての モデルマスター を一旦 JSON 形式のファイルにエクスポートし、そのJSONファイルをアップロードすることで一括して モデル として反映する仕組みになっています。 GS2 の管理画面で モデルマスター を操作して JSON 形式のファイルにエクスポートして利用しても構いませんが、Excel や独自の管理ツールを作成し GS2 上に モデルマスター を一切登録せずに モデル にデータを反映することもできます。

また、GS2-Deploy のテンプレート内でマスターデータを管理することもできます。この場合 git などの バージョン管理ツール で取り扱いやすくなりますので、こちらも検討してみてください。

運営上都合のいい方法でマスターデータを管理してください。

GS2サービスの拡張

GS2-Script を使って GS2-Inventory にアイテムを付与する例

-- 引数からモデル情報を取得
namespace_name = args['namespaceName']
user_id = args['userId']
inventory_name = args['inventoryName']
item_name = args['itemName']
acquire_count = args['acquireCount']
expires_at = args['expiresAt']

inventory_client = gs2('inventory')

-- リクエストを発行
result = inventory_client.acquire_item_set_by_user_id({
    namespace_name=namespace_name,
    user_id=user_id,
    inventory_name=inventory_name,
    item_name=item_name,
    acquire_count=acquire_count,
    expires_at=expires_at,
})

-- レスポンスを応答
if(result['isError']) then
    fail(result['statusCode'], result['errorMessage'])
end

result = result['result']

GS2 は一般的な用途においては標準機能でゲームシステムを構築できるよう設計しています。 しかし、ゲーム内のユースケースによっては GS2 の標準機能では実現できないことが出てくるかもしれません。

そのようなケースに対応できるよう GS2 では Lua によるスクリプトによる機能拡張に対応しています。 GS2-Account であれば、アカウントの新規作成時 アカウントの認証時 引き継ぎ設定登録時 引き継ぎ実行時 といったタイミングで GS2-Script に登録したスクリプトを実行できるようにしています。 これによって、 引き継ぎ設定をしたときに報酬をプレゼントボックスに届けたい というようなニーズに応えられるようにしています。 何度も引き継ぎ登録して報酬を受け取り放題になるのはゲームシステムに破綻をきたすので、1回だけ付与できるようにしたい場合は GS2-Limit の提供する回数制限機能と組み合わせて実装するなど、スクリプトの中で工夫を凝らしてください。

スタンプシート

GS2ではGS2内の各サービス間で連携して処理を行うため、スタンプシートという仕組みがあります。 GS2を使用していただくうえで、いずれスタンプシートは使っていただくことになると思われます。 本項は事前に読んでおいていただいても、スタンプシートを使用する場面が来た時に読んでいただくのでも構いません。

例えばゲーム内通貨を実現するGS2-Moneyとゲーム内の所持品を実現するGS2-Inventoryを組み合わせて、 通貨でアイテムを購入するといった動作をスタンプシートで実現します。 ここでGS2-Moneyに通貨を消費する要求を、GS2-Inventoryにアイテムを取得する要求を別々に送る場合、 処理の途中でアプリが停止した場合やチート行為によって、片方の要求だけを処理してしまう可能性があります。

一方で、スタンプシートは消費アクション(ここでは通貨の消費)と入手アクション(ここではアイテムの入手)がひとまとまりになったものです。 今回はアイテムを通貨で購入する例ですので、ゲーム内の商品を実現するGS2-Showcaseの商品マスターに商品を登録します。 この商品に購入したときに発行するスタンプシートを登録します。 GS2-Showcaseと商品マスターについてはGS2-Showcaseのページをご確認ください。

GS2-Showcaseにスタンプシートを登録出来たら、次はクライアントでそのスタンプシートを入手して実行します。 GS2-Showcaseでは'Buy' というメソッドでスタンプシートを取得できます。 次に入手したスタンプシートを実行することで通貨の消費とアイテムの取得が処理されます。

今回はアイテムの購入を例に紹介しましたが、他にもGS2-Questでスタミナを消費してクリアアイテムを取得する、のようにスタンプシートを使う場面は複数あります。 またスタンプシート一つに複数の消費アクションと入手アクションを設定することもできます。

ただし複数の入手アクションを設定した場合は、GS2-JobQueueと連携して処理を行う必要があります。 これは、報酬を付与する際に報酬を管理するサーバーがダウンしていると、芋づる式にいろいろなサービスが利用できなくなることを避けるためです。 そこで一度スタンプシート実行時に報酬処理をGS2-JobQueueに登録しておいて、報酬処理の実行が一度失敗してもリトライできるような仕組みを提供しています。 この点についてはGS2-JobQueueのページで詳しく説明しています。

GS2-SDKのページの冒頭にもスタンプシートの説明と消費アクション、入手アクションの一覧があります。

スタンプシートを実行するサンプルコード(Unity)

スタンプシートを実行するサンプルコード(Unity)


    //UnityEvent<Gs2Exception>型を使用するための準備
    [System.Serializable]
    public class OnErrorCallback : UnityEngine.Events.UnityEvent<Gs2Exception>
    {
    }

    //スタンプシート実行エラー時の動作を定義
    private void OnError(Exception e)
    {
        Debug.Log(e.ToString());
    }

    private IEnumerator StampSheetTest()
    {
        var machine = new StampSheetStateMachine(stampSheet, client, distributorNamespeceName, stampSheetEncryptKeyId);
        UnityEvent<Gs2Exception> m_events = new OnErrorCallback();
        m_events.AddListener(OnError);
        yield return machine.Execute(m_events);
    }

スタンプシート実行完了時に動かすメソッドを登録する例(Unity)

    machine.OnCompleteStampSheet.AddListener(Machine_OnCompleteStampSheet);//machine.Executeを実行する前に登録しておく

    private void Machine_OnCompleteStampSheet(EzStampSheet sheet, Gs2.Unity.Gs2Distributor.Result.EzRunStampSheetResult result)
    {
     //スタンプシート実行完了時の処理を書く
    }

まず4つの引数を使ってスタンプシートステートマシンを作ります。

次にスタンプシートステートマシンの持つExecuteを実行します。 Executeの引数には UnityEvent型でエラー時の処理を登録する必要があります。

またスタンプシートステートマシンには、スタンプシートの実行が完了したときに動作させるメソッド、コールバックを登録することができます。 Executeを実行する前に2つ目のサンプルコードのようにコールバックを追加しておきます。 こうしておくことでExecuteを実行後、エラー時と成功時でそれぞれのコールバックが実行されます。

ダウンロード

GS2-SDK for GameEngine

Game Server Services は 主要なゲームエンジンから利用できるSDKを提供しています。 ゲームエンジン向け SDK では、ゲーム内から利用することにフォーカスして通常の SDK より高レベルなAPI形式で提供しています。

GS2 SDK for Unity

本 SDK 自身は Apache License 2.0 で提供されています。 プログラムのどこかで Apache License 2.0 で提供されているライブラリを使用していることを明示する必要があります。

本 SDK にはパブリックドメインである LitJson(Gs2/Plugin/LitJson.dll) が含まれています。 この dll は GS2 SDK の動作の根幹に関わる動作に利用されているため、削除することが出来ません。

本 SDK には MIT License である websocket-sharp(Gs2/Plugin/websocket-sharp.dll) が含まれています。 表記すべきライセンスは以下です。 https://raw.githubusercontent.com/sta/websocket-sharp/master/LICENSE.txt この dll は GS2 SDK の動作の根幹に関わる動作に利用されているため、削除することが出来ません。

本 SDK には BSD License である protobuf(Gs2/Plugin/Google.Protobuf.dll) が含まれています。 表記すべきライセンスは以下です。 https://github.com/protocolbuffers/protobuf/blob/master/LICENSE この dll は GS2-Realtime を使用しなければ削除することが出来ます。

導入手順

Unity 2019.3 以降をご利用の場合

GS2 SDK for Unity Installer Version 2021.5.1

Unity Editor を起動し、メニューの Import Package から .unitypackage ファイルをインポートします。 その後、Unity Editor のメニューから 『Game Server Services > インストール』 を選択して、ウィザードの指示に従ってください。 インストール完了後、正しく動作しない場合があります。その場合は一度Unity Editorを再起動してみてください。

Unity 2019.2 以前をご利用の場合

GS2 SDK for Unity GitHub

Clone or Download を選択し、ダウンロードしたソースコードをプロジェクト内に配置します。

※ 上記インストーラーを利用する実装は Unity Package Manager を使用して SDK をプロジェクトに追加します。 しかし、 Unity Editor の不具合によって、2019.2 以前では正しく動作しません

Unity Release Note 2019.3.0 Package Manager: Fixed an issue where using some npm registry backends as scoped registries would fail with an error like com.foo.bar: Cannot read property '0.0.1' of undefined. (1177614)

実装上の諸注意

Windows向けにビルドするときはBuildSettingsでx86からx86_64に変更してください。x86ではエラーが出ます。

GS2 SDK for Unreal Engine 4

本 SDK 自身は Apache License 2.0 で提供されています。 プログラムのどこかで Apache License 2.0 で提供されているライブラリを使用していることを明示する必要があります。

本 SDK には Game Server Services 株式会社によってカスタマイズされた以下のソフトウェアが含まれています。

これらは SDK の動作の根幹に関わる動作に利用されているため、削除することができません。 これらのソフトウェアにおける、 Game Server Service 株式会社による改変部分のライセンスは、各ソフトウェアの規定するところに基づき、 Apache License 2.0 で提供されています。 それ以外の部分については、各ソフトウェアのライセンスに従います。 いずれのライセンスも、各ソフトウェアの著作権表示とライセンスの全文を、配布するソフトウェアの複製に含める必要があります。

ダウンロード

GS2 SDK for Unreal Engine 4 Version 2021.7.2

導入手順

SDK のダウンロードパッケージを展開し、ご使用の Unreal Engine 4 プロジェクトに対して、以下の変更を行います。

  1. Source/(プロジェクト名) 以下の任意の場所に gs2-unreal-engine-sdk/gs2 ディレクトリをコピーします。
  2. (プロジェクト名).Build.cs に以下の変更を加えます。
    • PublicDependencyModuleNames に "HTTP" および "WebSockets" を追加します。
      • 例: PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HTTP", "WebSockets" });
    • PublicSystemIncludePaths に GS2 SDK for Unreal Engine 4 の gs2 ディレクトリがある場所を追加します。
      • 例: PublicSystemIncludePaths.Add(System.IO.Path.Combine(ModuleDirectory, "gs2-unreal-engine-sdk/"));
  3. (プロジェクト名).uproject のコンテキストメニューから Visual Studio プロジェクトを再生成します。
iOS ビルドをご利用の場合

Unreal Engine 4.26 現在、 iOS ビルドではエンジンの持つルート CA 証明書が正しく読み込まれない問題があり、そのままでは GS2 サーバとの接続に失敗するため、以下の手順で回避してください。

  1. エンジンの Engine/Content/Certificates/ThirdParty/cacert.pem を、プロジェクトの Content/Certificates/cacert.pem へコピーする
  2. 「プロジェクト設定 (Project Settings)」の「パッケージ化 (Packaging)」詳細設定の中にある「コピーする追加の非アセットディレクトリ (Additional Non-Assets Directories to Copy)」に Certificates を追加する

なお、上記設定は iOS 以外をターゲットとする場合でも変更する必要はありません。

実装上の諸注意

GS2 SDK

本 SDK 自身は Apache License 2.0 で提供されています。 プログラムのどこかで Apache License 2.0 で提供されているライブラリを使用していることを明示する必要があります。

GS2-Java-SDK

https://github.com/gs2io/gs2-java-sdk

GS2-PHP-SDK

https://github.com/gs2io/gs2-php-sdk

GS2-Golang-SDK

https://github.com/gs2io/gs2-golang-sdk

GS2-Python-SDK

https://github.com/gs2io/gs2-python-sdk

GS2-Typescript-SDK

https://github.com/gs2io/gs2-typescript-sdk

サービス紹介・利用料金

GS2-Account

サービス概要

ユーザを識別するためのアカウント管理機能を提供するサービスです。

デバイスの機種変更時にデータを引き継げるようにするために メールアドレス+パスワード や ソーシャルアカウントを利用したデータの引き継ぎ機能に対応しています。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

引き継ぎ情報に関して、同一ユーザの情報の登録・更新・削除は1秒間に3回以内に抑えるようにしてください。 異なるユーザであればこの制限はありません。

基本的な使い方

ネットワーク機能を実装するゲームにはアカウント管理は必須です。 なぜなら、個人を特定しないと所持品の管理や、フレンドの管理といったネットワーク機能の多くの要素を実現できないからです。

アカウントに関して、GS2 では2種類の方針を用意しています。

アカウント管理の仕組み

GS2 では、アカウントの管理機能を実現するために GS2-Account というサービスを提供しています。

匿名アカウント

匿名アカウントの発行実装例(Unity)

yield return gs2.Account.Create(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.AccountId); // string ゲームプレイヤーアカウント
            Debug.Log(r.Result.Item.UserId); // string アカウントID
            Debug.Log(r.Result.Item.Password); // string パスワード
            Debug.Log(r.Result.Item.TimeOffset); // integer 現在時刻に対する補正値(現在時刻を起点とした秒数)
            Debug.Log(r.Result.Item.CreatedAt); // long 作成日時
        }
    },
    namespaceName   //  ネームスペース名
);

最初に GS2-Account が発行するアカウントは 匿名アカウント と呼ばれるカテゴリのアカウントです。 匿名アカウントとは 利用者を特定することはできますが、ゲームプレイヤーが誰なのかを特定する情報をもたないアカウントです。

「なぜ、そんなアカウントを発行するのか」というと、ゲームを開始するときにいきなりメールアドレスを聞いたりするのは、離脱率を上げてしまうからです。 そのため、利用者を特定するのに十分な要素として、GS2-Account はアカウントの新規作成APIを呼び出すとランダムなIDとパスワードを発行します。 アクセス元のクライアントは発行されたIDとパスワードをローカルストレージに保存し、ログイン処理にはその情報を利用します。

引き継ぎ設定

引き継ぎ設定登録の実装例(Unity)

yield return gs2.Account.AddTakeOverSetting(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.TakeOverId); // string 引き継ぎ設定
            Debug.Log(r.Result.Item.UserId); // string ユーザーID
            Debug.Log(r.Result.Item.Type); // integer スロット番号
            Debug.Log(r.Result.Item.UserIdentifier); // string 引き継ぎ用ユーザーID
            Debug.Log(r.Result.Item.Password); // string パスワード
            Debug.Log(r.Result.Item.CreatedAt); // long 作成日時
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    type,   //  スロット番号
    userIdentifier,   //  引き継ぎ用ユーザーID
    password   //  パスワード
);

引き継ぎ実行の実装例(Unity)

yield return gs2.Account.DoTakeOver(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.AccountId); // string ゲームプレイヤーアカウント
            Debug.Log(r.Result.Item.UserId); // string アカウントID
            Debug.Log(r.Result.Item.Password); // string パスワード
            Debug.Log(r.Result.Item.TimeOffset); // integer 現在時刻に対する補正値(現在時刻を起点とした秒数)
            Debug.Log(r.Result.Item.CreatedAt); // long 作成日時
        }
    },
    namespaceName,   //  ネームスペース名
    type,   //  スロット番号
    userIdentifier,   //  引き継ぎ用ユーザーID
    password   //  パスワード
);

匿名アカウントは登録シーケンスが不要というメリットがありますが、当然デメリットもあります。それは、ゲームプレイヤー自身も自分のIDとパスワードを把握していないということです。

そこで、GS2-Account では 引き継ぎ設定 という機能を用意しています。 引き継ぎ設定とは、匿名アカウントをよりゲームプレイヤーが認識しやすいID/パスワードとして表現するためのもので 一つの匿名アカウントに対して複数の引き継ぎ設定を行えるようになっています。

たとえば、スロット1 には メールアドレス任意のパスワード を設定できるようにし、 スロット2 には SNS の アカウント名 などの情報を登録することになります。 あとは、機種変更を行ったり、異なるデバイスで同じアカウントにログインしたいと思ったときには 引き継ぎ設定で登録したID/パスワード情報を入力することで、再度匿名アカウントのログイン情報を取得できます。

異なるデバイスからのログインを止めたい

GS2-Gateway で同時ログインを許可しない例(Unity)

yield return gs2.Gateway.SetUserId(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.ConnectionId); // string コネクションID
            Debug.Log(r.Result.Item.OwnerId); // string オーナーID
            Debug.Log(r.Result.Item.NamespaceName); // string ネームスペース名
            Debug.Log(r.Result.Item.UserId); // string ユーザーID
            Debug.Log(r.Result.Item.CreatedAt); // long 作成日時
            Debug.Log(r.Result.Item.UpdatedAt); // long 最終更新日時
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    false   //  同時に異なるクライアントからの接続を許容するか
);

GS2-Account は引き継ぎを実行した際に匿名アカウントのパスワードを変更する機能があります。 この機能を利用すると、引き継ぎ実行前のデバイスからのログインをできなくすることができます。

しかし、より厳密にログイン制限を行いたい場合はこの方法では不十分です。 たとえば、セーブデータをまるっと異なるデバイスにコピーした場合に、複数のデバイスが正しいID/パスワードを持った状態を作り出すことができます。 このようなケースに対応したければ、 GS2-Gateway の同時ログインを制限する機能を利用するべきです。

GS2-Gateway は WebSocket を使って GS2 のサーバと接続し、サーバで発生したイベント たとえば「フレンド申請が来た」「新しいプレゼントがプレゼントボクスに届いた」「マッチメイキングが完了した」といった通知を受け取るための仕組みです。

この機能の性質上、WebSocket の通信セッションに対してログイン中のユーザIDを紐付ける必要があり この紐付け処理を実行する際に「すでに該当ユーザIDがログイン中の場合は接続を許可しない」ということが実現できます。

作成したアカウント情報をもとにログインする

GS2-Account で署名付きアカウント情報を取得する実装例(Unity)

yield return gs2.Account.Authentication(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.AccountId); // string ゲームプレイヤーアカウント
            Debug.Log(r.Result.Item.UserId); // string アカウントID
            Debug.Log(r.Result.Item.Password); // string パスワード
            Debug.Log(r.Result.Item.TimeOffset); // integer 現在時刻に対する補正値(現在時刻を起点とした秒数)
            Debug.Log(r.Result.Item.CreatedAt); // long 作成日時
            Debug.Log(r.Result.Body); // string 署名対象のアカウント情報
            Debug.Log(r.Result.Signature); // string 署名
        }
    },
    namespaceName,   //  ネームスペース名
    userId,   //  アカウントID
    keyId,   //  認証トークンの暗号化に使用する暗号鍵 のGRN
    password   //  パスワード
);

GS2-Auth で署名付きアカウント情報からアクセストークンを取得する実装例(Unity)

yield return gs2.Auth.Login(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Token); // string アクセストークン
            Debug.Log(r.Result.UserId); // string ユーザーID
            Debug.Log(r.Result.Expire); // long 有効期限
        }
    },
    userId,   //  ユーザーID
    keyId,   //  署名の作成に使用した暗号鍵 のGRN
    body,   //  アカウント認証情報の署名対象
    signature   //  署名
);

GS2-Account のログイン処理は2ステップで実装されています。

  1. GS2-Account に匿名アカウントのユーザID/パスワードを送信して、パスワード検証を通過した場合に署名付きのアカウント情報を応答
  2. GS2-Auth に 署名付きアカウント情報 を送信し、署名検証に通過した場合に ユーザID のアクセストークンを発行

この2ステップをひとまとめにしたものがGS2-Profile::Loginです。こちらについては、はじめかた⇒サンプルコードで解説しています。

アクセストークンの有効期限

アクセストークンには有効期限が設定されています。 そのため、取得したアクセストークンを永続化して利用することは推奨できません。

アクセストークンの有効期限は アクセストークン取得時の戻り値に含まれています。 有効期限を迎える前に再度アクセストークンの取得処理を行う必要があります。

GS2-Auth

サービス概要

GS2-Auth は GS2 内でゲームプレイヤーを特定するための”アクセストークン”を発行するサービスです。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

GS2-Chat

サービス概要

テキストベースのチャット機能を提供します。

メッセージデータはルームごとに管理され、過去24時間分のログが保持されます。 ルームにはパスワードを設定でき、設定した場合はメッセージの取得や投稿リクエストにパスワードが必要となります。 ルームにはユーザIDのホワイトリストを設定でき、設定した場合はホワイトリストに含まれるゲームプレイヤーにしかメッセージの取得や投稿ができなくなります。

メッセージにはカテゴリを設定でき、クライアント側でペイロードのパース方法を切り替えることができます。 たとえば、 カテゴリ0 はテキストがペイロードにそのまま含まれる。 カテゴリ1 はペイロードにスタンプのIDが含まれる。といった使い方ができます。

ルームを購読すれば、ルームに対して新しい投稿があったときにサーバからプッシュ通知を受け取ることができます。 このとき、通知を受けたいカテゴリを設定できますので、メッセージの種類や重要度別にカテゴリを分ければ、ゲームプレイヤーが通知を受け取るメッセージの種類を設定できるようになりユーザ体験を向上させることができます。 また、購読の設定には モバイルプッシュ通知に転送するか という設定もありますので、うまく活用してください。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

1つのルームに対して、1秒間に3回までしか投稿できません。 1ルームに参加できる人数を極端に多くする、一斉に投稿を促すような実装を避けてください。 1つのルームに対して購読できる最大人数は1000人です。

GS2-Datastore

サービス概要

任意のバイナリデータをサーバに保存する機能を提供します。 アップロードされたデータはアクセス権限管理(ACL - Access Control List)が適用されます。

データには誰でもデータにアクセスが可能な public 指定したユーザIDのゲームプレイヤーにのみアクセスが可能な protected 自身のみがアクセスが可能な private の3種類のACLが設定できます。

アップロードされたデータは自動的にバックアップが作成され、 データを更新・削除したとしても30日以内であれば復元が可能です。 アップロードされたデータには固有のID(UUID v4)と世代IDが割り当てられ、 データを更新・削除すると世代IDが更新されます。 データをダウンロードする際には世代IDを指定して、具体的なファイルを特定します。

データを更新するのと同時に他プレイヤーがデータにアクセスしようとしたときに 意図せず新しいバージョンのデータを取得しないようにダウンロードリクエストには世代IDを含めることができます。 世代IDをダウンロードリクエストに付加することで、確実にリストアップした時点でのデータをダウンロードすることを保証することができます。

ただし、いつまでも世代の古いデータにアクセスできることは望まないゲームもあるかもしれません。 そのため、データの所有者以外は、更新後60分以内かつ1つ前の世代に限り古い世代のデータをダウンロードを許可するオプションが存在します。

本機能を使用してセーブデータの管理をする際には、不正行為に対する耐性を考えてください。 他のGS2のサービスではゲームの仕様に合わせて加算・減算を自由に行えないようコントロールされています。 しかし、ローカルのセーブデータを信頼することはチート行為の原因となりえます。 GS2の機能が提供されている場合はそちらを優先して使用し、 UGCコンテンツの交換や、コンフィグの設定値など改ざんされても影響が軽微な要素のみを管理するようにしてください。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

ゲームによってはUGCコンテンツ(レースゲームのゴーストデータやステージのエディットデータ)を他のプレイヤーと共有したいことがあるかもしれません。 このようなときに使用できるのがこのデータストア機能です。

アクセス権限

データストアは任意のバイナリデータをサーバにアップロードできます。 アップロードしたデータにはアクセス権限を設定できます。 アクセス権限にはいくつかの方針があり、データごとに設定ができます。

パブリック

ランキングのスコアにゴーストデータを添付したいような場合に使用します。 スコアのメタデータとして、ゴーストデータのIDを格納しておくことで、ランキングを取得した際に、そのスコアを達成したレースのゴーストをデータストアから取得できるような設計ができます。

プロテクト

特定の相手にのみ公開したい情報。例えば「チャットルームに写真をアップロードして、ルームの参加者にのみアクセス権限を付与したい」というようなケースで使用できます。

プライベート

クラウドセーブのような機能を実現したい場合に使用できます。

データのアップロード

データのアップロードは3つのステップで構成されます。 - アップロード用のURLを取得 - データをアップロード - アップロードの完了を報告 3ステップに分かれている理由は、GS2Datastoreはバイナリデータをサーバーに保存・読込するため管理機能を提供しますが、 実際バイナリデータを保存するのはGS2上ではなくファイルサーバーになるためです。 そのため、①GS2にデータの名前やアクセス権等の管理情報をリクエストにファイルサーバーにアップロードするためのURLを取得、 ②取得したURLにHTTPクライアントでデータをアップロード、③アップロードが無事完了したことをGS2に報告する、 の3ステップになっています。

アップロード用のURLを取得

ファイルをアップロードする前にデータ名やアクセス権等の管理情報をもとにアップロード用のURLを取得します。 ここで得られたURLに対して HTTP クライアントで PUT リクエストとしてアップロードすることになります。

アップロード用のURLを取得例(Unity)

yield return gs2.Datastore.PrepareUpload(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.DataObjectId); // string データオブジェクト
            Debug.Log(r.Result.Item.Name); // string データの名前
            Debug.Log(r.Result.Item.UserId); // string ユーザーID
            Debug.Log(r.Result.Item.Scope); // string ファイルのアクセス権
            Debug.Log(r.Result.Item.AllowUserIds); // list[string] 公開するユーザIDリスト
            Debug.Log(r.Result.Item.Status); // string 状態
            Debug.Log(r.Result.Item.Generation); // string データの世代
            Debug.Log(r.Result.Item.CreatedAt); // long 作成日時
            Debug.Log(r.Result.Item.UpdatedAt); // long 最終更新日時
            Debug.Log(r.Result.UploadUrl); // string アップロード処理の実行に使用するURL
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    scope,   //  ファイルのアクセス権
    allowUserIds   //  公開するユーザIDリスト
);

データをアップロード

得られた URL に対してアップロードを実行します。 アップロードはGS2ではなくファイルサーバに HTTP クライアントで PUT リクエストを用いて行います。

アップロードの完了を報告

無事アップロードが完了したことを報告します。 この報告をもって、次にダウンロード用のURLを取得するときに最新のデータが置かれたURLをGS2から返すことができます。

アップロードの完了を報告例(Unity)

yield return gs2.Datastore.DoneUpload(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.DataObjectId); // string データオブジェクト
            Debug.Log(r.Result.Item.Name); // string データの名前
            Debug.Log(r.Result.Item.UserId); // string ユーザーID
            Debug.Log(r.Result.Item.Scope); // string ファイルのアクセス権
            Debug.Log(r.Result.Item.AllowUserIds); // list[string] 公開するユーザIDリスト
            Debug.Log(r.Result.Item.Status); // string 状態
            Debug.Log(r.Result.Item.Generation); // string データの世代
            Debug.Log(r.Result.Item.CreatedAt); // long 作成日時
            Debug.Log(r.Result.Item.UpdatedAt); // long 最終更新日時
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    dataObjectName,   //  データの名前
);

ヘルパー関数

GS2 SDK for Unity では3ステップのアップロードプロセスを1つのAPIにまとめたヘルパー関数が用意されています。

ヘルパー関数の利用例(Unity)

yield return gs2.Datastore.Upload(
    r =>
    {
        if (r.Error != null) throw r.Error;
        result = r.Result;
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    scope,   //  ファイルのアクセス権
    allowUserIds,   //  公開するユーザIDリスト
    binary   // byte配列 のバイナリデータ
);

データのダウンロード

データのダウンロードは2つのステップで構成されます。 - ダウンロード用のURLを取得 - データをダウンロード アップロードと違い完了を報告する必要がないため2ステップになります。

ダウンロード用のURLを取得

データを上げたユーザーIDとデータの名前をもとにダウンロード用のURLを取得します。 ここで得られたURLに対して HTTP クライアントで GET リクエストとしてダウンロードすることになります。

ダウンロード用のURLを取得例(Unity)

yield return gs2.Datastore.PrepareDownloadByUserIdAndDataObjectName(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.DataObjectId); // string データオブジェクト
            Debug.Log(r.Result.Item.Name); // string データの名前
            Debug.Log(r.Result.Item.UserId); // string ユーザーID
            Debug.Log(r.Result.Item.Scope); // string ファイルのアクセス権
            Debug.Log(r.Result.Item.AllowUserIds); // list[string] 公開するユーザIDリスト
            Debug.Log(r.Result.Item.Status); // string 状態
            Debug.Log(r.Result.Item.Generation); // string データの世代
            Debug.Log(r.Result.Item.CreatedAt); // long 作成日時
            Debug.Log(r.Result.Item.UpdatedAt); // long 最終更新日時
            Debug.Log(r.Result.FileUrl); // string ファイルをダウンロードするためのURL
            Debug.Log(r.Result.ContentLength); // long ファイルの容量
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    userId,   //  ユーザーID
    dataObjectName,   //  データの名前
);

データをダウンロード

得られた URL に対してダウンロードを実行します。 ダウンロードはGS2ではなくファイルサーバに HTTP クライアントで GET リクエストを用いて行います。

GS2-Deploy

サービス概要

サービスのデプロイを補助するサービスです。

ゲームが必要とするリソースを記述したテンプレートを適用することで、GS2の各サービスのリソースを作成できるサービスです。 GS2-Deploy を使ったリソース管理を行うことで、開発環境と製品環境で設定を揃えたり、開発中に開発者ごとの環境を作成したりするのが容易となります。 また、イベントを開催するときにも、イベントに必要な要素をテンプレート化して登録し、終わったらそれを削除すれば、イベント開催前の状態に容易に戻すことができます。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

クレデンシャルを発行する GS2-Deploy テンプレートの例

基本的な使い方

GS2TemplateFormatVersion: "2019-05-01"
Description: GS2 SDK identifier template Version 2019-07-10

Globals:
  Alias:
    ApplicationUserName: application

Resources:
  IdentifierApplicationUser:
    Type: GS2::Identifier::User
    Properties:
      Name: ${ApplicationUserName}

  IdentifierApplicationUserAttachPolicy:
    Type: GS2::Identifier::AttachSecurityPolicy
    Properties:
      UserName: ${ApplicationUserName}
      SecurityPolicyId: grn:gs2::system:identifier:securityPolicy:ApplicationAccess
    DependsOn:
      - IdentifierApplicationUser

  IdentifierApplicationIdentifier:
    Type: GS2::Identifier::Identifier
    Properties:
      UserName: ${ApplicationUserName}
    DependsOn:
      - IdentifierApplicationUser

Outputs:
  ApplicationClientId: !GetAttr IdentifierApplicationIdentifier.Item.ClientId
  ApplicationClientSecret: !GetAttr IdentifierApplicationIdentifier.ClientSecret

GS2では基本的にネームスペースの作成やアイテムの定義などのリソースの作成を、マネージメントコンソール上で一つ一つ操作・入力しながら作成します。 このマネージメントコンソール上での操作・入力をyaml形式のテンプレートファイルで記述して、リソースを作成できるようにしたものがGS2-Deployです。 また特徴として、一度インプットしたテンプレートファイルの一部を追記・削除した場合、即座にリソースに反映されます。 インプットしたテンプレートファイルそのものを削除すれば、そのテンプレートファイルで作成されたリソースは削除されます。

以上の特徴から以下の使い道が考えられます。

GS2-Dictionary

サービス概要

アイテム図鑑やキャラクター図鑑のようなプレイヤー・エントリー毎に「手に入れた」「手に入れない」の二値を持つデータベースを実現します。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

使い方は3ステップです。

  1. エントリーモデルを定義する
  2. アイテムやキャラクターなどを入手するイベントを契機にエントリーを「手に入れた」状態にする
  3. ゲーム内からエントリーを取得する

エントリーモデルを定義する

マネージメントコンソールなどからアイテムやキャラクターの存在を表す、エントリーモデルを定義します。 この時、図鑑の種類ごとにネームスペースを分けることを推奨します。 これは図鑑を開く時にエントリーの一覧を取得しますが、ネームスペースごとに取得するためです。 GS2-InventoryのItemの入手経験をGS2-Dictionaryで管理する場合はItemNameとEntryNameを一致させると、プログラムで扱いやすいことが考えられます。 また、使用用途として図鑑で説明していますが、図鑑に限らず2値でサーバーに保管したい情報があればご活用ください。

アイテムやキャラクターなどを入手するイベントを契機にエントリーを「手に入れた」状態にする

クライアントからチートによる嘘の入手報告が行えないように、セキュリティポリシー'ApplicationAccess' ではエントリーの入手報告ができません。 GS2のイベントが入手の契機になる場合は、スタンプシートやGS2-Scriptから入手報告をしてください。 またはサーバーからGS2に入手報告をすることもできます。

ゲーム内からエントリーを取得する

ゲーム内から記録されたエントリーを取得してUIを構築します。

GS2-Distributor

サービス概要

プロパティの増加処理を中継し、対象の所持数量の上限に達していた場合に GS2-Inbox に転送する機能を提供します。 この機能を利用することで、所持数量の上限に到達したときの複雑な分岐処理を無くすことができ、意図しないデータ消失のリスクを回避できます。

その他に、GS2内で一貫性のある処理を実現するための仕組みであるスタンプシートの実行処理にも使用します。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

本機能はAPIを呼び出すものではなく設定をして用意しておくものになります。 使い方は2つです。

スタンプシートの実行処理に利用する

GS2ではプロパティ(ゲーム内通貨やスタミナ、所持品など)の増減の処理にはスタンプシートという仕組みを使用します。 スタンプシートの詳細はGS2-SDKの冒頭をご覧ください。 スタンプシートの実行する際、引数の一つにGS2-Distributorのネームスペースが必要になります。 スタンプシートを実行するだけならネームスペースの作成だけで大丈夫です。

所持限界のプロパティをGS2-Inboxに転送する機能

スタンプシートを実行するとき、プロパティの所持上限を超える可能性があります。 この時、超えたプロパティを自動でGS2-Inboxに転送することができます。 こちらはマネージメントコンソールから配信設定マスターを作ることで使用できます。 また転送するプロパティを指定することもできます。 これは例えば、経験値上限の時に取得した経験値がGS2-Inboxに転送され続けいっぱいなってしまう事態を回避するためなどに使用できます。

GS2-Enhance

サービス概要

GS2-Inventory で管理された素材アイテムを消費し、GS2-Experience の経験値を得る仕組みを提供します。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

GS2-Exchange

サービス概要

アイテムの売却価格や、レアリティが異なる進化素材間の交換レートなど、常設される交換処理を実現します。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

使い方は2ステップです。

  1. 交換モデルを定義する
  2. 交換を実行する

交換モデルを定義する

マネージメントコンソールから交換モデル設定します。 お金とゲーム内通貨の交換のほか、ゲーム内通貨でガチャを回したりスタミナを増やしたりなど様々な定義ができます。

交換を実行する

交換を実行する例(Unity)

yield return gs2.Exchange.Exchange(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.Name); // string 交換レートの種類名
            Debug.Log(r.Result.Item.Metadata); // string 交換レートの種類のメタデータ
            Debug.Log(r.Result.Item.ConsumeActions); // list[ConsumeAction] 消費アクションリスト
            Debug.Log(r.Result.Item.AcquireActions); // list[AcquireAction] 入手アクションリスト
            Debug.Log(r.Result.StampSheet); // string 交換処理の実行に使用するスタンプシート
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    rateName,   //  交換レートの種類名
    count,   //  交換するロット数
    config   //  設定値(オプション値)
);

ここで注意する点は'exchange' 自体を実行するだけではリソースの交換は行われないことです。 'exchange'の返り値であるスタンプシートを処理することで処理が行われます。 スタンプシートについては はじめかた⇒スタンプシートのページをご確認ください。 また一つの交換モデルに複数の報酬を設定する場合はGS2-JobQueueと連携する必要があります。

GS2-Experience

サービス概要

キャラクターやスキルのレベル、親愛度など、経験値を積み重ねてランクアップしていく仕組みの実現に使用します。 ランクキャップ機能も有しており、キャラクターやスキルなど個別の要素ごとに上限管理を行うことができます。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

同一プロパティに対する経験値付与は1秒間に3回までにおさえてください。 異なるユーザや同一ユーザでも異なるプロパティに対する経験値付与であればこの制限はありません。

基本的な使い方

キャラクターやアイテム、スキルなどの成長を管理するためのサービスとして、 GS2 には GS2-Experience が用意されています。

GS2-Experience が提供するのは、主に以下の機能です。

以下の機能については、 GS2-Experience は関知しません。

ただし、 GS2-Stamina など別の GS2 のサービスと連携することで、 GS2-Experience のランクに連動してスタミナの最大値を拡張させたりすることができます。

経験値モデルの登録

経験値モデルは JSON 形式のマスターデータとして登録します。 マスターデータのフォーマットは こちら のリンクに資料があります。

マスターデータは、マネージメントコンソールで要素ごとにデータを登録し、その結果をエクスポートすることで用意することもできます。 エクスポートしたマスターデータを明示的に登録するまで GS2-Experience の挙動には反映されないことに注意してください。

経験値モデルの設定値

経験値モデルはランク体系、たとえばキャラクターレベルやスキルレベルといった成長要素の種類を表現するものです。 『どのランクアップ閾値テーブルを使用するか』や『デフォルトのランクキャップ』、『ランクキャップの引き上げ限界』といった設定が可能です。

ランクアップ閾値テーブル

ランクアップ閾値テーブルはランクアップの閾値となる経験値の配列です。 たとえば、[100, 200, 300] と設定した場合、

経験値の値 ランク
0~99 1
100~199 2
200~299 3
300 4

となり、 300 を超えて経験値を獲得しようとしても、超えた分の経験値は切り捨てられます。

ランクキャップ

ランクキャップ は、到達可能なランクの最大値です。 たとえば、ランクアップ閾値テーブルに指定されている値が [100, 200, 300] で、ランク4までの設定があったとしても、ランクキャップが 2 に設定されている場合、到達できるランクは 2 までとなり、また 100 を超えて経験値を入手できなくなります。 現在のランクキャップの値は、経験値や現在のランクの値同様に個々のキャラクターやスキルなどごとに持つことができます。 ランクキャップは経験値モデルごとの ランクキャップの引き上げ限界 まで引き上げることができ、ランクキャップを引き上げることによって、入手できる経験値の最大量も同時に拡張されます。

経験値の入手

現在獲得している経験値は、経験値モデルとプロパティIDの組み合わせごとに保持されます。

そのため、経験値の入手処理を実行する際にも、獲得する経験値量のほかに、経験値モデルとプロパティIDの組み合わせを指定する必要があります。 プロパティIDとは経験値を付与する対象の識別子で、 GS2-Experience への事前の登録なく任意の値を指定できます。

たとえば、GS2-Inventory で管理している所持キャラクターに対して経験値を付与したい場合は、GS2-Inventory の『所持品ID』をそのままプロパティIDに指定できます。 ゲームプレイヤー自身に経験値を付与したい場合は、GS2-Account の『ユーザID』をそのまま指定できます。

また、所持キャラクターに複数の経験値を持たせたい場合、たとえば『戦闘スキル』と『信頼度』のようにランク体系が異なるのであれば、異なる経験値モデルを指定することで、 GS2-Inventory の『所持品ID』1つに対して複数の経験値を持たせることができます。 一方、『剣スキル』と『弓スキル』のように、武器スキルという同じランク体系のなかで複数の経験値を持たせたい場合は、同様の設定を持つ経験値モデルを複数用意する方法もありますが、 GS2-Inventory の『所持品ID』のうしろに -sword や -bow などの文字列を追加してプロパティIDを区別する方法もあります。

経験値の入手とセキュリティ

経験値の入手はセンシティブな操作です。 経験値の入手に関してクライアントから任意の操作を受け付けることは、不正に経験値を増殖させ、ゲーム性を大きく損なうことになりかねません。

そこで、GS2 ではスタンプシートの報酬としてしか経験値の入手を行えないようにしています。 スタンプシートの報酬の内容はサーバに定義を持ち、また報酬を得る前に対価の支払いやゲーム内目標の達成をおこなったことをスタンプシートの仕組みが保証するため、経験値の不正な増殖を防げます。 したがって、経験値の入手には、ゲーム内ストアでの購入や、クエストの報酬として入手するような報酬設計が必要です。

現在の経験値の取得

経験値を取得する方法は2種類あります

特定のキャラクターのプロパティページを表示したい場合、後者を使用するほうが効率がいいでしょう。

経験値の取得コード例(Unity)

yield return gs2.Experience.GetStatus(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.ExperienceName); // string 経験値の種類の名前
            Debug.Log(r.Result.Item.PropertyId); // string プロパティID
            Debug.Log(r.Result.Item.ExperienceValue); // long 累計獲得経験値
            Debug.Log(r.Result.Item.RankValue); // long 現在のランク
            Debug.Log(r.Result.Item.RankCapValue); // long 現在のランクキャップ
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    experienceName,   //  経験値の種類の名前
    propertyId,   //  プロパティID
);

TIPS: パーティに編成されたキャラクターへの経験値付与

GS2 では複数のリソースを編成するためのサービスとして GS2-Formation が用意されています。 GS2-Formation を利用すると、個別に指定をおこなうことなく、編成されたリソースの全体に報酬として経験値を付与することができます。 これによって、パーティに編成されているキャラクターなどに対して、一括で簡単に経験値を付与することができます。

TIPS: ステータスの正当性保証

ランクに応じて何らかの機能を開放するなどのユースケースで、クライアントが送信してきたランク値が正当なのかを検証したくなることがあります。 GS2-Experience はそのようなニーズに応えるために、署名(※)付きのステータスを応答する機能があります。

この機能を利用することで、サーバ間通信を行わず、クライアントが送信してきたステータスの値を信用していいかを判断することができるようになります。 繰り返しステータスを使用した操作を行う場合、署名付きのステータスをクライアントからサーバに渡すことで、通信回数の削減や通信時間の削減ができます。

ただし、署名付きステータスは取得時の値でしかありませんので、ステータスに変化があった場合はクライアント側で再取得を行ったうえでサーバに渡す必要があります。 署名付きステータスには応答時刻が付与されており、 GS2 のサービスでは、取得から1時間以上経過した署名付きステータスは使用できなくなります。

※ 署名とは暗号技術の一種で、とあるデータが改ざんされていないかを検出するために使用できる値です。

GS2-Formation

サービス概要

装備やパーティ編成機能を実現します。

編成情報を記録する フォーム(Form) と、編成した フォーム を保存する 保存したフォーム(Mold) があります。 パーティ編成を例にすると、キャラクターを フォーム に設定し、パーティを編成します。 編成したパーティ情報を複数記録する場合は 保存したフォーム を使って実現できます。

保存したフォーム に保存できる数にはキャパシティを設定でき、キャパシティの値は引き上げることができます。

フォーム に編成するプロパティはプロパティIDで指定することになりますが、プロパティの正規表現で値を限定することができます。 また、GS2-Inventory のリソースを設定する場合は、GS2-Inventory が発行する 署名付きアイテムセット を使って編成対象に指定できます。 署名付きアイテムセット とは、該当のアイテムを所有していることを保証する署名付きプロパティ情報で、こちらを使う場合はクライアントから直接編成することを許します。

この 所有していることを保証する とは編成時点での保証であり、編成後にプロパティを手放した場合のフォローはありません。 GS2-Inventory でプロパティを消費したり売却したりする場合は、事前に GS2-Formation で編成に使用されていないかの判定はクライアントまたはスクリプトで実装する必要があります。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

同一フォームの更新処理は1秒間に3回以内に抑えてください。

基本的な使い方

使い方は4ステップです。

  1. フォームモデルマスターを定義する
  2. フォームの保存領域(Mold)モデルマスターを定義する
  3. フォームを作成する
  4. フォームをフォームの保存領域(Mold)に保存する

フォームモデルマスターを定義する

フォームモデルマスターはマネージメントコンソールで作成できます。 例えばキャラクター5人のパーティー情報を保存したい場合は、スロットを5つ設定しスロットモデル名にchara1~5のように入力するとよいでしょう。 注意点として、マネージメントコンソールからはフォーム一つ当たり10までしかスロットを設定できません。 それ以上のスロットを設定する場合は一度スロットが足りない状態で保存しておいて、マスターデータをエクスポートし編集してアップロードしてください。

フォームの保存領域(Mold)モデルマスターを定義する

フォームの保存領域(Mold)モデルマスターはマネージメントコンソールで作成できます。 フォームの保存領域(Mold)モデルマスターは作成したフォームモデルマスターにしたがって作成したフォームをいくつ保存できるようにするかを設定します。 初期キャパシティと最大キャパシティを設定できます。 例えばゲームの進行度に合わせてキャパシティを増やしたり、ゲーム内通貨でキャパシティを購入するといったことができます。

フォームを作成する

署名付きアイテムセットを取得する例(Unity)

yield return gs2.Inventory.GetItemWithSignature(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Items); // list[ItemSet] 有効期限毎の{model_name}
            Debug.Log(r.Result.ItemModel.Name); // string アイテムモデルの種類名
            Debug.Log(r.Result.ItemModel.Metadata); // string アイテムモデルの種類のメタデータ
            Debug.Log(r.Result.ItemModel.StackingLimit); // long スタック可能な最大数量
            Debug.Log(r.Result.ItemModel.AllowMultipleStacks); // boolean スタック可能な最大数量を超えた時複数枠にアイテムを保管することを許すか
            Debug.Log(r.Result.ItemModel.SortValue); // integer 表示順番
            Debug.Log(r.Result.Inventory.InventoryId); // string インベントリ
            Debug.Log(r.Result.Inventory.InventoryName); // string インベントリモデル名
            Debug.Log(r.Result.Inventory.CurrentInventoryCapacityUsage); // integer 現在のインベントリのキャパシティ使用量
            Debug.Log(r.Result.Inventory.CurrentInventoryMaxCapacity); // integer 現在のインベントリの最大キャパシティ
            Debug.Log(r.Result.Body); // string 署名対象のアイテムセット情報
            Debug.Log(r.Result.Signature); // string 署名
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    inventoryName,   //  インベントリの種類名
    itemName,   //  アイテムモデルの種類名
    keyId,   //  署名の発行に使用する暗号鍵 のGRN
    itemSetName   //  アイテムセットを識別する名前(オプション値)
);

署名付きスロットのリストを作成する例(Unity)

    List<EzSlotWithSignature> slots = new List<EzSlotWithSignature>();
    EzSlotWithSignature slot = new EzSlotWithSignature();
    slot.PropertyType = "gs2_inventory"; //gs2_inventoryのプロパティを使用する
    slot.Body = result.Body; //GetItemWithSignatureの返り値
    slot.Signature = result.Signature; //GetItemWithSignatureの返り値
    slot.Name = "chara1"; //スロット名(例えばキャラクター5人パーティならchara1~5分作成する)
    slots.Add(slot); //実際はフォームのスロットの数だけ、スロットを作成してAddする

基本的な使い方としてクライアント側でGS2-Inventoryで管理している所持品を編成してフォームを作成する例を説明します。 この時、所持していないアイテムを編成できないようにGS2-Inventory が発行する'署名付きアイテムセット' を使用します。 これを'署名付きスロットのリスト' にあてはめてフォームを作成します。

フォームをフォームの保存領域(Mold)に保存する

署名付きスロットのリストを作成する例(Unity)

yield return gs2.Formation.SetForm(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.Name); // string フォームの保存領域の名前
            Debug.Log(r.Result.Item.Index); // integer 保存領域のインデックス
            Debug.Log(r.Result.Item.Slots); // list[Slot] スロットリスト
            Debug.Log(r.Result.Mold.Name); // string フォームの保存領域の名前
            Debug.Log(r.Result.Mold.UserId); // string ユーザーID
            Debug.Log(r.Result.Mold.Capacity); // integer 現在のキャパシティ
            Debug.Log(r.Result.MoldModel.Name); // string フォームの保存領域名
            Debug.Log(r.Result.MoldModel.Metadata); // string メタデータ
            Debug.Log(r.Result.MoldModel.FormModel.Name); // string フォームの種類名
            Debug.Log(r.Result.MoldModel.FormModel.Metadata); // string フォームの種類のメタデータ
            Debug.Log(r.Result.MoldModel.FormModel.Slots); // list[SlotModel] スリットリスト
            Debug.Log(r.Result.MoldModel.InitialMaxCapacity); // integer フォームを保存できる初期キャパシティ
            Debug.Log(r.Result.MoldModel.MaxCapacity); // integer フォームを保存できるキャパシティ
            Debug.Log(r.Result.FormModel.Name); // string フォームの種類名
            Debug.Log(r.Result.FormModel.Metadata); // string フォームの種類のメタデータ
            Debug.Log(r.Result.FormModel.Slots); // list[SlotModel] スリットリスト
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    moldName,   //  フォームの保存領域の名前
    index,   //  保存領域のインデックス
    slots,   //  編成するスロットのリスト
    keyId,   //  署名の発行に使用した GS2-Key の暗号鍵GRN
);

作成した'署名付きスロットのリスト' を引数にsetFormを実行します。 この時'署名付きアイテムセット' の発行に使用した暗号鍵も引数に指定します。

GS2-Friend

サービス概要

ゲーム内の友達関係を実現するときに使用します。

リクエストを出して、承認されて初めて関係の構築されるフレンドと、 相手の承認手続きなしに構築できるフォローがあります。

ゲームプレイヤーのメタデータとしてプロフィール情報を持たせることができます。 プロフィール情報は 公開 フォロワーに公開 フレンドに公開 のスコープがあり、スコープに応じて他プレイヤーに公開されます。

フレンド・フォロワー数の上限はそれぞれ1万人ですが、連携するサービスによっては各サービスのポリシーに従って追加の制限が加わる可能性があります。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

同一ゲームプレイヤーによるプロフィールの更新は1秒間に3回までにおさえてください。 異なるユーザや同一ユーザでも異なるプロパティに対する経験値付与であればこの制限はありません。

1人のプレイヤーにフレンドリクエストが集中する仕様は避けてください。 1人のプレイヤーがフレンドリクエストを受け付けられるのは1秒間に3回までです。

基本的な使い方

使い方は大きく3つあります。

プロフィール

プロフィールを設定する例(Unity)

yield return gs2.Friend.UpdateProfile(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.UserId); // string ユーザーID
            Debug.Log(r.Result.Item.PublicProfile); // string 公開されるプロフィール
            Debug.Log(r.Result.Item.FollowerProfile); // string フォロワー向けに公開されるプロフィール
            Debug.Log(r.Result.Item.FriendProfile); // string フレンド向けに公開されるプロフィール
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    publicProfile,   //  公開されるプロフィール(オプション値)
    followerProfile,   //  フォロワー向けに公開されるプロフィール(オプション値)
    friendProfile   //  フレンド向けに公開されるプロフィール(オプション値)
);

他人に公開する情報を設定します。 全体向け・フォロワー向け・フレンド向けのそれぞれ設定することができます。

フォロー

フォローを行う例(Unity)

yield return gs2.Friend.Follow(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.UserId); // string ユーザーID
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    targetUserId,   //  フォローされるユーザID
);

相手の承認手続きなしに構築できる関係がフォローです。フォローの解除もできます。 フォローを行うとフォローしたプレイヤーの一覧とそのプレイヤーのフォロワー向けメッセージの取得ができます。

フレンド

リクエストを出して、承認されて構築される関係がフレンドです。

リクエストを出す側ができることは

リクエストを受けた側ができることは

サンプルコードはGS2-SDK for GameEngineでご確認ください。

GS2-Gateway

サービス概要

GS2-Gateway は WebSocket を経由して GS2 にアクセスするためのプロキシ機能を提供します。 GS2-Gateway を使用して GS2 のサーバを利用することで、常時接続しながら通信できるようになります。これによって、サーバーとの通信速度が改善することが期待できます。

また、常時接続できることから、 サーバーサイドからのプッシュ通知に対応 できます。 このプッシュ通知機能があると GS2-Mission で ミッションのタスク を達成したときや、 GS2-Matchmaking で ギャザリング の参加者の増減があった時などに通知を受け取ることができるようになります。

プッシュ通知対象のデバイスがオフラインだった場合、 Firebase (https://firebase.google.com/) を使用したモバイルプッシュ通知に転送する仕組みも提供します。 この機能を使用すれば、マッチメイキングが完了したときにプレイヤーがオフラインだった場合はモバイルプッシュ通知を出してゲームに戻ってくるようプレイヤーを誘導することができます。

GS2-Gateway で常時接続用のセッションを構築する際にゲームプレイヤーの識別を行えるよう GS2-Auth で発行した アクセストークン で認証処理を行うことになりますが、 すでに同一ユーザのセッションが存在する場合は、アクセスを拒否することができます。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

WebSocket通信をするところから、プッシュ通知を受け取るところまで3ステップで説明します。

  1. WebSocket通信を開始する
  2. サーバーでプッシュ通知を送る設定をする
  3. プッシュ通知を受け取ったときの処理を定義する

WebSocket通信をする

サンプルコード

WebSocket通信を開始する例(Unity)

yield return gs2.Gateway.SetUserId(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.ConnectionId); // string コネクションID
            Debug.Log(r.Result.Item.NamespaceName); // string ネームスペース名
            Debug.Log(r.Result.Item.UserId); // string ユーザーID
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    allowConcurrentAccess,   //  同時に異なるクライアントからの接続を許容するか
);

サーバーでプッシュ通知を送る設定をする

プッシュ通知を送る方法は3つあります。

  1. GS2が用意しているプッシュ通知を使う
  2. GS2-Scriptを使う
  3. 自作のサーバーからGS2SDKを使う

GS2が用意しているプッシュ通知を使う

GS2-Mission で ミッションのタスク を達成したときや、 GS2-Matchmaking で ギャザリング の参加者の増減があった時など,GS2が用意しているプッシュ通知を使うことができます。 プッシュ通知を送信するサービスのネームスペースからプッシュ通知の有無を設定できます。 例えばGS2-Matchmaking で ギャザリング のマッチングが完了したときは、"Gs2Matchmaking:Complete"というメッセージを送ります。

GS2-Scriptを使う

プッシュ通知を用意していないGS2のイベントからプッシュ通知を送りたい場合や、メッセージの内容を自分で決めたい場合はこちらを使用します。 詳細はGS2-Scriptを確認してください。

自作のサーバーからGS2SDKを使う

GS2のイベント以外を契機にプッシュ通知を送る場合はこちらの方法を利用ください。

サーバーからプッシュ通知を送信する例(Python)

from gs2_gateway_client.request import SendNotificationRequest
from gs2_gateway_client.result import SendNotificationResult

result = client.send_notification(
    SendNotificationRequest()\
        .with_namespace_name(namespace_name)\
        .with_user_id(user_id)\
        .with_subject(subject)\
        .with_payload(payload)\
        .with_enable_transfer_mobile_notification(enable_transfer_mobile_notification)\
        .with_sound(sound)
)
# エラー発生時には例外が発生
# result が成功結果が格納

プッシュ通知を受け取ったときの処理を定義する

プッシュ通知を受け取ったときの処理を定義する例(Unity)

//プッシュ通知が届いたときに動かす関数を定義します
public void PushNotificationHandler(NotificationMessage message)
{
    Debug.Log(message.issuer);  //プッシュ通知が起因したイベント
    Debug.Log(message.subject);  //プッシュ通知のタイトル
    Debug.Log(message.payload);  //プッシュ通知の内容

    if (message.issuer.StartsWith("Gs2Matchmaking:")){
        if (message.issuer.EndsWith(":Join"))
        {
            //ギャザリングに新たに参加者が増えた時の処理
            var notification = JsonMapper.ToObject<JoinNotification>(message.payload);
            Debug.Log(notification.joinUserId); //新たにギャザリングに参加したユーザーのID
        }
        else if (message.issuer.EndsWith(":Leave"))
        {
            //ギャザリングから参加者が減ったときの処理
            var notification = JsonMapper.ToObject<LeaveNotification>(message.payload);
            Debug.Log(notification.leaveUserId); //ギャザリングから退室したユーザーのID
        }
        else if (message.issuer.EndsWith(":Complete"))
        {
            //マッチングが完了したときの処理
        }
    }
}

//定義した関数をプッシュ通知が届いたときに呼び出されるように設定します
gs2Client.profile.Gs2Session.OnNotificationMessage += PushNotificationHandler;

最後にプッシュ通知が届いたときにクライアントでどのように処理するか定義します。 ここでは例としてGS2-Matchmakingに用意されたプッシュ通知を利用した例を記載します。

GS2-Identifier

サービス概要

GS2にアクセスするためのクレデンシャルや権限管理をおこないます。

GS2にアクセスするときにはクレデンシャルを使用してAPIを呼び出します。 その際にはクレデンシャルの所有者であるユーザーに割り当てられたセキュリティポリシーに基づいて処理されます。 複数のセキュリティポリシーをユーザーに割り当てている場合、いずれかのセキュリティポリシーによって操作が許可されていればAPIを利用できます。

またマネージメントコンソールログインパスワードを作成することで複数人で1つのプロジェクトを管理できます。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

使い方は3ステップに分かれています。

  1. セキュリティポリシーを用意する
  2. ユーザーを作成し、セキュリティポリシーを割り当てる
  3. 作成したユーザーでAPIを呼び出したり、マネージメントコンソールにログインする

セキュリティポリシーを用意する

GS2では初めから、開発者用の全てのAPIを利用する権限AdministratorAccess とユーザー用のチート行為に繋がらないAPIのみが呼び出せる権限ApplicationAccess が用意されています。 また、セキュリティポリシーを作成することも可能です。

ポリシードキュメントのフォーマット
Actions に呼び出せるアクションを羅列し、Resources に操作出来る対象リソースを羅列する
Actions / Resources には末尾にのみワイルドカードを使用出来る

{
    'Version': '2016-04-01',
    'Statements': [
        {
            'Effect': 'Allow',
            'Actions': [
                'Gs2Account:Create*',
            ],
            'Resources': ['*'],
        },
    ]
}

ユーザーを作成し、セキュリティポリシーを割り当てる

セキュリティポリシーが準備できたらユーザーを作成します。 ユーザーには複数セキュリティポリシーを割り当てることができます。 その場合、いづれかのセキュリティポリシーで許可されているAPIが実行可能になります。

作成したユーザーでAPIを呼び出す

クレデンシャルを使ってユーザー認証する例(Unity)
はじめかたのサンプルコードにより詳しく各言語で載せています

    var profile = new Gs2.Unity.Util.Profile(
        clientId: 'クレデンシャルのID',
        clientSecret: 'クレデンシャルのパスワード',
        reopener: new Gs2BasicReopener()
    );

    {
        AsyncResult<object> asyncResult = null;
        var current = profile.Initialize(
            r => { asyncResult = r; }
        );
        yield return current;
    {
    var gs2 = new Gs2.Unity.Client(profile); //gs2から各種APIを呼び出す

ユーザーを作成したらクレデンシャルを作成します。 クレデンシャルとはそのユーザーであることを認証するためのIDとパスワードです。 このIDとパスワードをプログラムに組み込み、GS2に認証を要求することによってAPIを使用できるようになります。

作成したユーザーでマネージメントコンソールにログインする

マネージメントコンソールログインパスワードを設定することで、別の開発者がマネージメントコンソールにログインできるようになります。 パスワードを作成したらログイン用のURLが生成されますので、その二つを別の開発担当者に通知することでログインできます。 ユーザーに割り当てられているセキュリティポリシーによって利用できる機能は制限されます。

GS2-Inbox

サービス概要

プレゼントつきのメッセージ機能を提供するサービスです。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

使い方は4ステップになります。

  1. プレゼントボックスを作る
  2. メッセージを送信する
  3. メッセージを受信する
  4. メッセージについている報酬を受け取る

プレゼントボックスを作る

ネームスペースがそのままプレゼントボックスの役割をします。 メッセージの種類ごとにプレゼントボックスを分けたい場合は、ネームスペースを複数作成してください。

メッセージを送信する

個別メッセージを送る例(Python)

from gs2_inbox_client.request import SendMessageByUserIdRequest
from gs2_inbox_client.result import SendMessageByUserIdResult

result = client.send_message_by_user_id(
    SendMessageByUserIdRequest()\
        .with_namespace_name('namespace-0001')\
        .with_user_id('user-0001')\
        .with_metadata('{"type": "message", "body": "hello"}')\
        .with_read_acquire_actions(read_acquire_actions)\
        .with_expires_at(expires_at)\
        .with_expires_time_span(expires_time_span)
)
# エラー発生時には例外が発生
# result が成功結果が格納

全ユーザーに送る例(Python)

from gs2_inbox_client.request import CreateGlobalMessageMasterRequest
from gs2_inbox_client.result import CreateGlobalMessageMasterResult

result = client.create_global_message_master(
    CreateGlobalMessageMasterRequest()\
        .with_namespace_name('namespace-0001')\
        .with_name('globalMessageMaster-0001')\
        .with_metadata('{"type": "globalMessageMaster", "body": "hello"}')\
        .with_read_acquire_actions([
Object("AcquireAction", {"action": 'Gs2Inventory:AcquireItemSetByUserId', "request": 'Gs2Inventory:AcquireItemSetByUserId-request'})
])\
        .with_expires_time_span(expires_time_span)\
        .with_expires_at(expires_at)
)
# エラー発生時には例外が発生
# result が成功結果が格納

送信方法は2つあります。

・特定の1ユーザーもしくは複数ユーザーに送る ・全ユーザーに送る(グローバルメッセージ)

メッセージの送信はサーバーからGS2SDKを使うか、マネージメントコンソールからも送ることができます。 またメッセージには報酬をつけることができます。

メッセージを受信する

ここで気を付ける点は、個別メッセージとグローバルメッセージで受信するためのAPIが異なることです。 グローバルメッセージは一度受信すると以後個別メッセージとして保管されます。

個別メッセージを受け取る例(Unity)

yield return gs2.Inbox.List(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Items); // list[Message] メッセージのリスト
            Debug.Log(r.Result.NextPageToken); // string リストの続きを取得するためのページトークン
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    pageToken,   //  データの取得を開始する位置を指定するトークン(オプション値)
    limit   //  データの取得件数(オプション値)
);

全体メッセージを受け取る例(Unity)

yield return gs2.Inbox.ReceiveGlobalMessage(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item); // list[Message] 受信したメッセージ一覧
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
);

メッセージについている報酬を受け取る

メッセージについている報酬を受け取る例(Unity)

yield return gs2.Inbox.Read(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.MessageId); // string メッセージ
            Debug.Log(r.Result.Item.Name); // string メッセージID
            Debug.Log(r.Result.Item.Metadata); // string メッセージの内容に相当するメタデータ
            Debug.Log(r.Result.Item.IsRead); // boolean 既読状態
            Debug.Log(r.Result.Item.ReadAcquireActions); // list[AcquireAction] 開封時に実行する入手アクション
            Debug.Log(r.Result.Item.ReceivedAt); // long 作成日時
            Debug.Log(r.Result.Item.ReadAt); // long 最終更新日時
            Debug.Log(r.Result.Item.ExpiresAt); // long メッセージの有効期限
            Debug.Log(r.Result.StampSheet); // string スタンプシート
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    messageName   //  メッセージID
);

メッセージには報酬がついている場合があります。 メッセージを既読にするAPIを実行することで報酬の内容が記載されたスタンプシートを得ます。 このスタンプシートを実行することで報酬を得ます。 スタンプシートについては はじめかた⇒スタンプシートのページをご確認ください。 サンプルコードの引数'messageName' には受信で得た'message' の 'messageId' ではなく'name' を指定することに注意してください。 また一つのメッセージに複数の報酬を設定する場合はGS2-JobQueueと連携する必要があります。

GS2-Inventory

サービス概要

所持品の管理機能を提供します。

アイテムを入れるカバンのような存在をインベントリと呼びます。 インベントリにはキャパシティを設定でき、キャパシティは後で拡張することができます。 課金通貨を使ったり、クエストの報酬でキャパシティを拡張することができます。

アイテムには有効期限を設定できます。 有効期限の切れたアイテムは使用できなくなり、アイテムを使用する際には明示的に有効期限を指定しなければ有効期限の近いアイテムから消費されます。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

同一プロパティに対する所持数量の増減処理は1秒間に3回までにおさえてください。 異なるプロパティでもインベントリにとって初めて入手する、インベントリのアイテムを使い切る操作の場合は、インベントリ内の操作で1秒間に3回までにおさえてください。 異なるプロパティに対する所持数量の増減であればこの制限はありません。

基本的な使い方

GS2 では所持品を管理するための仕組みとして GS2-Inventory というサービスを提供しています。 所持品と見なせるゲーム内要素にはさまざまな種類がありますが、GS2-Inventory はそれら全てを取り扱えるよう設計しています。 たとえば、以下のようなものです。

GS2-Inventory は所持数量のみを管理し、使用した際の効果の実装には GS2-Exchange などを用いてリソースの交換設計(たとえば、スタミナドリンクを対価としてスタミナ値を回復する報酬を得るというような)を行うことになります。

インベントリ・アイテムセット

インベントリの取得例(Unity)

yield return gs2.Inventory.GetInventory(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.InventoryId); // string インベントリ
            Debug.Log(r.Result.Item.InventoryName); // string インベントリモデル名
            Debug.Log(r.Result.Item.CurrentInventoryCapacityUsage); // integer 現在のインベントリのキャパシティ使用量
            Debug.Log(r.Result.Item.CurrentInventoryMaxCapacity); // integer 現在のインベントリの最大キャパシティ
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  カテゴリー名
    inventoryName   //  インベントリの種類名
);

GS2-Inventory では所持品を管理する単位として、 アイテムセットインベントリ という概念があります。 アイテムセット は、「スタミナドリンク×1個」や「傷薬×30個」といった、アイテムの種類とその個数の組み合わせです。 また、 インベントリ はアイテムセットを格納する鞄のようなものです。 実際にゲームで使用する際には、キャラクター・消費財・通貨 など、UIで一覧表示させたいカテゴリごとにインベントリを分割して利用するのが効果的です。

所持しているアイテムの取得例(Unity)

yield return gs2.Inventory.ListItems(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Items); // list[ItemSet] 有効期限ごとのアイテム所持数量のリスト
            Debug.Log(r.Result.NextPageToken); // string リストの続きを取得するためのページトークン
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  カテゴリー名
    inventoryName,   //  インベントリの種類名
    pageToken,   //  データの取得を開始する位置を指定するトークン(オプション値)
    limit   //  データの取得件数(オプション値)
);

所持品枠

インベントリは所持品枠を持ち、アイテムセット1個につき1個の所持品枠を占有します。 所持品枠の数は有限であり、これを超えてアイテムセットを所持することはできません。 所持品枠の数はゲームプレイヤーごとに拡張できるようになっており、課金通貨やリソースを使用して拡張できるよう設計できます。

同一アイテムの複数所持

GS2-Inventory では、アイテムの種類ごとに、1つのアイテムセットに格納可能な最大個数を設定できます。 キャラクターや装備品のように、一つ一つを区別する必要があるアイテムではこの最大個数を 1 に設定します。 一方、消費物や強化素材のように、たくさん所持することが前提となっているアイテムでは 99 や 999 などに設定します。

また、アイテムの種類ごとに、そのアイテムのアイテムセットを複数作成できるかを設定することができます。 この設定を有効にすることで、複数の所持品枠を占有することで、1アイテムセット当たりの最大個数を超えてアイテムを所持できるようになります。

アイテムの種類の特徴に応じて、たとえば以下のような設定が考えられます。

アイテムの種類 1つのアイテムセットに格納可能な最大個数 同一種類のアイテムセットを複数作成できるか
キャラクターや装備品など 1 OK
消費物や強化素材 99 OK
ゲーム内通貨 999999999 NG

有効期限

所持品には有効期限を設定できます。有効期限の切れた所持品は勝手に削除されます。 イベント期間中にのみ使用できるアイテムログインボーナスとして当日のみ使用できるスタミナドリンクを配布 というような使い方ができます。

種類が同じでも、有効期限の異なるアイテムは別のアイテムセットが作成されます。 その際、同一種類で複数のアイテムセットの作成ができないように設定されたアイテムの場合は入手ができない可能性があります。

インベントリモデル・アイテムモデルの登録

インベントリモデル・アイテムモデルは JSON 形式のマスターデータとして登録します。

マスターデータは、マネージメントコンソールで要素ごとにデータを登録し、その結果をエクスポートすることで用意することもできます。 エクスポートしたマスターデータを明示的に登録するまで GS2-Inventory の挙動には反映されないことに注意してください。

アイテムの入手

アイテムセットに入りきらなかったり、インベントリの所持品枠が足りなかったりして全量を入手できなかった場合は、入りきる分だけがインベントリに格納され、あふれた個数が応答されます。 また、あふれたアイテムは、ネームスペースに設定したスクリプトや、 GS2-Distributor を利用することで、プレゼントボックスへ転送することができます。

必ず新しいアイテムセットを作るように指定した場合、新しいアイテムセットがインベントリに入りきらなければ、既存のアイテムセットに空きがあっても、あふれたものとして扱われます。

アイテムを格納するアイテムセットを指定した場合、そのアイテムセットに入りきらなければ、ほかのアイテムセットやインベントリに空きがあっても、あふれたものとして扱われます。 また、指定したアイテムセットの内容と、入手しようとしたアイテムの種類や期限が一致しない場合はエラーになります。

いずれの指定もない場合、アイテムは、インベントリの所持枠の占有がもっともすくなくなるように格納されます。

アイテムの入手とセキュリティ

アイテムの入手はセンシティブな操作です。 アイテムの入手に関してクライアントから任意の操作を受け付けることは、不正にアイテムを増殖させ、ゲーム性を大きく損なうことになりかねません。

そこで、GS2 ではスタンプシートの報酬としてしかアイテムの入手を行えないようにしています。 スタンプシートの報酬の内容はサーバに定義を持ち、また報酬を得る前に対価の支払いやゲーム内目標の達成をおこなったことをスタンプシートの仕組みが保証するため、アイテムの不正な増殖を防げます。 したがって、アイテムの入手には、ゲーム内ストアでの購入や、クエストの報酬として入手するような報酬設計が必要です。

アイテムの消費

GS2の思想としては、スタンプシートの対価としてアイテムの消費は行われるべきです。 しかし、ローカルリソースに対して報酬を与えられるようにGS2では消費に関してはAPIを用意しています。

アイテム消費の例(Unity)

yield return gs2.Inventory.Consume(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Items); // list[ItemSet] 消費後の有効期限ごとのアイテム所持数量のリスト
            Debug.Log(r.Result.ItemModel.Name); // string アイテムモデルの種類名
            Debug.Log(r.Result.ItemModel.Metadata); // string アイテムモデルの種類のメタデータ
            Debug.Log(r.Result.ItemModel.StackingLimit); // long スタック可能な最大数量
            Debug.Log(r.Result.ItemModel.AllowMultipleStacks); // boolean スタック可能な最大数量を超えた時複数枠にアイテムを保管することを許すか
            Debug.Log(r.Result.ItemModel.SortValue); // integer 表示順番
            Debug.Log(r.Result.Inventory.InventoryId); // string インベントリ
            Debug.Log(r.Result.Inventory.InventoryName); // string インベントリモデル名
            Debug.Log(r.Result.Inventory.CurrentInventoryCapacityUsage); // integer 現在のインベントリのキャパシティ使用量
            Debug.Log(r.Result.Inventory.CurrentInventoryMaxCapacity); // integer 現在のインベントリの最大キャパシティ
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  カテゴリー名
    inventoryName,   //  インベントリの名前
    itemName,   //  アイテムマスターの名前
    consumeCount   //  消費する量
);

アイテムを消費するアイテムセットを指定した場合、指定したアイテムセットに格納された個数で足りなければ、ほかのアイテムセットに余分なアイテムがあったとしても、個数不足として扱われます。

アイテムを消費するアイテムセットを指定しなかった場合、複数のアイテムセットをまたいでアイテムを消費することができます。 またその際、期限が早いアイテムセットから優先的に使用されます。

GS2-JobQueue

サービス概要

ジョブキュー機能を提供するサービスです。

ジョブキューはFIFOを保証したキューで、結果整合処理に使用できます。 結果整合処理とはAPIが応答した時点では処理の完了が保証されず、しばらくの時間の経過をもって”結果的に意図した状態になる”仕組みです。

GS2 では報酬付与の多くの部分を結果整合で処理します。 これは、報酬を付与する際に報酬を管理するサーバーがダウンしていると、芋づる式にいろいろなサービスが利用できなくなることを避けるためです。 報酬付与の処理をジョブキューに登録し、ジョブを実行する際に対象のサーバーが利用できない状態だったとしても、ジョブのリトライで結果整合を実現します。 リトライ回数には最大値を指定でき、最大値に達しても成功しなかった場合はデッドレタージョブという失敗したジョブが蓄積するモデルに格納されます。 デッドレタージョブを使って、処理の失敗したジョブに関して、個別対応を行えるようになっています。

GS2-JobQueue のジョブは勝手には実行されず、明示的に実行APIを呼び出す必要があります。 これにはジョブの戻り値をクライアント側で把握できるようにする目的があります。 例えば、GS2-Quest上でクエストをクリアしたあと、ジョブキューに報酬を付与するジョブが登録され、 クライアントはジョブキューを終端まで実行することでクエストによって得られた報酬付与処理を明示的に実行することができます。 (結果整合の遅延処理の完了を待つことが可能) なおかつ、そのジョブの戻り値を参照することで得られた報酬をUIに反映することができます。

ジョブの登録・実行は1秒間に3回までしか行なえません。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

同一ユーザに対するキューに対するジョブ登録は1秒間に3回までにおさえてください。 1回のジョブ登録で最大10個までジョブを登録できますので工夫をしてください。 ジョブの実行は1秒間に1回におさえてください。 異なるユーザに対する処理であればこの制限はありません。

基本的な使い方

1回の処理で複数の報酬が発生する場合に使用することになります。 例えば、複数のアイテムをセット売りする場合や10連ガチャなどがあります。

使い方は2ステップです

  1. ネームスペースの設定
  2. ジョブの実行

ネームスペースの設定

まずジョブをためるための場所、GS2-JobQueueのネームスペースを作ります。 次にジョブが発生する元のサービスのネームスペースからジョブの送り先になるGS2-JobQueueのネームスペースを指定します。 例えばGS2-Exchangeのネームスペース設定があります。 ジョブの送り元のネームスペースで送り先のGS2-JobQueueのネームスペースを指定するため、 GS2-JobQueueのネームスペースを複数作成し送り元別にジョブを管理することもできます。

またジョブが追加されたときにプッシュ通知を行う設定もできます。こちらはGS2-Gatewayを参照ください。

ジョブの実行

ジョブを実行する例(Unity)

yield return gs2.JobQueue.Run(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.JobId); // string ジョブ
            Debug.Log(r.Result.Item.ScriptId); // string ジョブの実行に使用するスクリプト のGRN
            Debug.Log(r.Result.Item.Args); // string 引数
            Debug.Log(r.Result.Item.CurrentRetryCount); // integer 現在のリトライ回数
            Debug.Log(r.Result.Item.MaxTryCount); // integer 最大試行回数
            Debug.Log(r.Result.Result.TryNumber); // integer 試行回数
            Debug.Log(r.Result.Result.StatusCode); // integer ステータスコード
            Debug.Log(r.Result.Result.Result); // string レスポンスの内容
            Debug.Log(r.Result.Result.TryAt); // long 実行日時
            Debug.Log(r.Result.IsLastJob); // boolean None
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
);

ジョブを実行するにはrunを使います。注意点としてrun1回ではジョブ1回の実行しか行いません。 返り値の'isLastJob' がfalseの場合はまだジョブが残っていますので、trueになるまで繰り返し実行してください。

GS2-Key

サービス概要

暗号鍵を管理するサービス

GS2内の機密データや、署名作成に使用する暗号鍵を作成します。 暗号鍵のデータはGS2の外に取り出すことができないため、安全に処理を行えます。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

単独で使用するものではなく、各サービスから呼び出して使用するものになります。

GS2-Limit

サービス概要

回数制限処理を実現するためのサービス

このサービスは単独で使うのではなく 他のサービスで回数制限機能を実現します。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

同一カウンターに対する操作は1秒間に3回までにおさえてください。 異なるユーザや、同一ユーザでも異なるカウンターに対する処理であればこの制限はありません。

基本的な使い方

使い方は3ステップです

  1. 回数制限マスターを作成する
  2. カウンターを増加する
  3. カウンターの値を取得する

回数制限マスターを作成する

マネージメントコンソールから作成できます。 カウンターの名前と定期的にリセットを行うかを設定することができます。

カウンターを増加する

カウンターを増加する方法は3つあります。

クライアントからAPIを呼び出す

クライアントからカウントアップする例(Unity)

yield return gs2.Limit.CountUp(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.CounterId); // string カウンター
            Debug.Log(r.Result.Item.Name); // string カウンターの名前
            Debug.Log(r.Result.Item.Count); // integer カウント値
            Debug.Log(r.Result.Item.CreatedAt); // long 作成日時
            Debug.Log(r.Result.Item.UpdatedAt); // long 最終更新日時
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    limitName,   //  回数制限の種類の名前
    counterName,   //  カウンターの名前
    countUpValue,   //  カウントアップする量(オプション値)
    maxValue   //  カウントアップを許容する最大値 を入力してください(オプション値)
);

該当するアクションを起こしたときにクライアントからGS2にカウントアップを要求する方法です。 注意する点として、カウントアップしたほうが有利な場合にユーザーが不正にAPI呼び出す可能性があることです。 これを回避したい場合はGS2-Identifierでカウントアップを呼び出せないようにポリシーを設定します。

GS2イベント発生時の報酬として設定する

たとえばクエストモデルマスターのクエストクリア時の報酬としてカウントアップを設定できます。 失敗時の報酬にも設定してクエスト成否にかかわらずカウントアップすることもできます。 他にも商品購入時の報酬に設定して購入回数をカウントアップする使い方もできます。

サーバーからAPIを呼び出す

サーバーからカウントアップする例(python)

from gs2_limit_client.request import CountUpByUserIdRequest
from gs2_limit_client.result import CountUpByUserIdResult

result = client.count_up_by_user_id(
    CountUpByUserIdRequest()\
        .with_namespace_name(namespace_name)\
        .with_limit_name(limit_name)\
        .with_counter_name(counter_name)\
        .with_user_id(user_id)\
        .with_count_up_value(count_up_value)\
        .with_max_value(max_value)
)

自作のサーバーから呼び出します。クライアントからAPIを呼び出すより安全です。

カウンターの値を取得する

カウンターの値を取得する例(Unity)

yield return gs2.Limit.GetCounter(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.CounterId); // string カウンター
            Debug.Log(r.Result.Item.Name); // string カウンターの名前
            Debug.Log(r.Result.Item.Count); // integer カウント値
            Debug.Log(r.Result.Item.CreatedAt); // long 作成日時
            Debug.Log(r.Result.Item.UpdatedAt); // long 最終更新日時
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    limitName,   //  回数制限の種類の名前
    counterName,   //  カウンターの名前
);

カウンターの現在値を確認します。この値によってクエスト挑戦を制限したり購入できる商品を変化させて下さい。

GS2-Lock

サービス概要

排他処理を実現するためのサービスです。

GS2内のAPIによるリソースの操作は、そのままでは排他されません。 スタンプシートによってリソースの増減を行うときは、自動的にこのサービスが利用され、対象リソースのIDをキーとしてロックを取得します。 スタンプシートを経由せずにリソースの増減を行う場合、明示的に GS2-Lock を使用してロック操作を行う必要があります。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

同一ミューテックスに対する操作は1秒間に3回までにおさえてください。 異なるミューテックスに対する処理であればこの制限はありません。

基本的な使い方

使い方は3ステップです。

  1. ネームスペースを作成する
  2. ロックする
  3. アンロックする

ネームスペースを作成する

マネージメントコンソールからネームスペースを作成します。特に設定の必要はありません。

ロックする

クライアントからロックする例(Unity)


yield return gs2.Lock.Lock(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.MutexId); // string ミューテックス
            Debug.Log(r.Result.Item.PropertyId); // string プロパティID
            Debug.Log(r.Result.Item.TransactionId); // string ロックを取得したトランザクションID
            Debug.Log(r.Result.Item.ReferenceCount); // integer 参照回数
            Debug.Log(r.Result.Item.TtlAt); // long ロックの有効期限
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  カテゴリー名
    propertyId,   //  プロパティID
    transactionId,   //  ロックを取得するトランザクションID
    ttl,   //  ロックを取得する期限(秒)
);

サーバーからロックする例(python)

from gs2_lock_client.request import LockByUserIdRequest
from gs2_lock_client.result import LockByUserIdResult

result = client.lock_by_user_id(
    LockByUserIdRequest()\
        .with_namespace_name(namespace_name)\
        .with_property_id(property_id)\
        .with_user_id(user_id)\
        .with_transaction_id(transaction_id)\
        .with_ttl(ttl)
)

クライアント、サーバーからそれぞれロックができます。 直接プロパティを編集する場合に用いるため、どちらかというとサーバーから使うものになります。 ライアントから実行する場合、ロックしてアンロックする前にクライアントが落ちるということがあれば、 プロパティがずっとロックされたままになりバグの原因になります。

アンロックする

クライアントからアンロックする例(Unity)


yield return gs2.Lock.Unlock(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.MutexId); // string ミューテックス
            Debug.Log(r.Result.Item.PropertyId); // string プロパティID
            Debug.Log(r.Result.Item.TransactionId); // string ロックを取得したトランザクションID
            Debug.Log(r.Result.Item.ReferenceCount); // integer 参照回数
            Debug.Log(r.Result.Item.TtlAt); // long ロックの有効期限
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  カテゴリー名
    propertyId,   //  プロパティID
    transactionId,   //  ロックを取得したトランザクションID
);

サーバーからアンロックする例(python)


from gs2_lock_client.request import LockByUserIdRequest
from gs2_lock_client.result import LockByUserIdResult

result = client.lock_by_user_id(
    LockByUserIdRequest()\
        .with_namespace_name(namespace_name)\
        .with_property_id(property_id)\
        .with_user_id(user_id)\
        .with_transaction_id(transaction_id)\
        .with_ttl(ttl)
)

GS2-Log

サービス概要

ログの集約・集計を実現するためのサービスです。

GS2に対するアクセスログや、スタンプシートによるリソース交換のログを検索・集計できるようになります。 ログの保管先は3種類用意されています。

どのマイクロサービスのログを集約するかを設定するには各サービスのネームスペースの設定値に GS2-Logs のネームスペースを設定しておこないます。 GS2でログを保管 / Google BigQuery でログを保管 を使用する場合は、ログの保存期間を設定できます。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

使い方は2ステップです。

  1. ネームスペースを作る
  2. ログを取得したいサービスのネームスペースからログの設定をする

ネームスペースを作る

マネージメントコンソールで作成します。ログの保管先だけ指定が必要です。

ログを取得したいサービスのネームスペースからログの設定をする

例えばGS2-Accountのネームスペース設定を見てください。 その中のログの出力先設定で、作成したGS2-Logのネームスペースを選択するとGS2-AccountのAPI呼び出しのログが保存されるようになります。 GS2-Accountのネームスペース分けている場合はそれぞれで設定が必要です。

GS2-Logのネームスペースを複数作成しておけば各サービスの各ネームスペースごとにログの送り先を別々にすることができます。 単純にサービス別にログを分ける他、複数人で管理する場合は管理担当ごとに分けるなども考えられます。

GS2-Lottery

サービス概要

抽選処理を実現するサービスです。

抽選処理は排出確率テーブルを元に行われます。 排出確率テーブルには、景品ごとの排出される重みを設定します。 例えば、景品Aに3を設定し、景品Bに1を設定した場合、景品Aの排出確率は75%、景品Bは排出確率は25%となります。

また、景品として他の排出確率テーブルを設定することもできます。 あらかじめSSR、SR、Rなどの同一レアリティごとに排出確率テーブルを用意しておき、それらを景品とした排出確率テーブルをつくることで、レアリティごとの排出確率を容易に設定できます。

抽選処理には2つのモードがあり、抽選の種類で設定できます。 1つ目は毎回変わらない確率で一様に抽選処理を行うモード、2つ目はボックスガチャモードです。 ボックスガチャとは、抽選処理を行うごとに景品を箱から取り出していき、最初に箱に入れた数と同回数抽選を行うと、必ずすべての景品が手に入るという方式です。 モードにボックスガチャを設定した場合は、排出テーブルに設定した重みの数だけ箱に景品が入った状態から抽選が始まります。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

使い方は2ステップです。

  1. 排出確立テーブルを作成する
  2. 抽選処理を実行する

マスターを作成する

まず排出確率テーブルマスターを作成します。各景品の出やすさを定義します。

排出確立は'重み' で設定します。例えば景品Aが重み1、景品Bが重み3の場合は景品Aが1/(1+3)=25%、景品Bが75%で排出されます。 また景品には排出確率テーブルを設定でき、木構造にできます。

例えば排出確率テーブル「レア」にレアアイテム1~2を重み1、排出確率テーブル「ノーマル」にノーマルアイテム1~7を重み1に設定します。 そのあと排出確率テーブル「ガチャ」に排出確率テーブル「レア」を重み1、排出確率テーブル「ノーマル」を重み7に設定します。 この場合、レアアイテム1が出る確率は(1/8)(1/2)=6.25%、ノーマルアイテム1が出る確率は(7/8)(1/7)=12.5%になります。

次に抽選の種類マスターを作成します。 

まず抽選モードを設定します。通常抽選は常に定められた確率で排出されます。BOX抽選は一度排出された景品は排出されなくなります。

次に抽選方法を設定します。先ほど作成した排出確率テーブルを使う場合は静的な抽選テーブルを選択します。その後、作成した排出確率テーブルを指定します。

抽選方法でGS2-Scriptによる動的抽選テーブルを選択した場合は、GS2-Scriptを利用して状態によって確率を変化させることができます。 GS2-Scriptをご確認ください。

抽選処理を実行する

ユーザー用のセキュリティポリシーであるApplicationAccess ではクライアントから直接抽選処理を行うAPIを呼び出すことはできません。 これは不正に抽選処理を実行するチート行為を阻止するためです。

クライアントから抽選処理を要求する場合は、他のサービスと連携することを想定しています。 たとえばマネージメントコンソールでGS2-Exchangeの交換レートマスターを開いてみてください。 入手アクションリスト⇒スタンプシートで実行するアクションの種類のリストの中に'Lottery: 抽選を実行'があります。 GS2-Exchangeではリソースの交換を実現する機能です。消費アクションにゲーム内通貨やガチャチケットなどを指定すれば、ゲーム内通貨やチケットを消費してガチャを回す機能を実現できます。 他にもGS2-Questと連携してステージクリア報酬のアイテムを抽選するという使い方もあります。

GS2-Matchmaking

サービス概要

対戦相手や協力相手を実現するサービスです。

マッチメイキングの流れは以下です。

ホストがギャザリングの作成 ↓ 参加者が条件にみあうギャザリングを検索 ↓ 規定人数が集まったらマッチメイキング完了

GS2-Matchmaking はこの流れのうち 参加者が条件にみあうギャザリングを検索 に関してできるだけ多くのニーズをみたせるよう設計されています。 ここでは、ユースケースを交えつつ、その設計例を解説します。

ゲーム内には、カジュアルプレイヤー向けと、コアゲーマー向けの2種類のゲームモードがあります。 これらのプレイヤーを混ぜることなくマッチメイキング処理を行いたいとします。

ギャザリングを作成する際にも、ギャザリングを検索する際にも、最大5つの属性値を指定できます。 ギャザリングを作成する際には募集するプレイヤーが持つ属性値の範囲を指定し、 ギャザリングを検索する際には、自身の属性値の値を指定して処理依頼をします。

つまり、ホストがギャザリングを作成する際に 属性値1 に募集するゲームモードを指定し、 検索する側も自分が参加したいゲームモードを 属性値1 に指定することで、希望するゲームモードが同じプレイヤー同士がマッチメイキングされます。

ホストはギャザリングを作成する際に 属性値2 に募集するレベルの最小値と最大値を指定します。 検索する側は自分のレベルを 属性値2 に指定することで、同じレベル帯のプレイヤー同士がマッチメイキングされます。

複数の属性値を指定した場合はすべての属性値の範囲をみたす相手を探すよう処理されます。

最初は狭い範囲で募集し、なるべく同じレベルのプレイヤー同士でマッチメイキングするが、なかなか対戦相手が見つからない場合、募集するレベル帯を広げて募集したいとします。 ギャザリングを作成しておよそ1分ごとに発火する GS2-Script イベントがあります。 このスクリプトにて、ギャザリングの属性値の範囲を緩和することで、徐々に希望する条件を緩和する処理を実装できます。

ギャザリングを作成するときのオプションとして、参加を許可するユーザIDリストを指定できます。 これを使い、フレンドのユーザIDリストを指定することで、参加者を限定することができます。

ギャザリングの作成時・検索時にユーザIDのブラックリストを指定できます。 検索時に指定したブラックリストは、条件に一致するギャザリングを発見し、参加したギャザリングのブラックリストに加えられます。 検索する際に自身がブラックリストに入っている場合はマッチメイキングの対象から除外されます。

ゲームによっては盾役1人、回復役1人、攻撃役2人でマッチメイキングを行いたいことがあります。 このときに使用できるのが ロール属性 です。

盾役として tank を、回復役として healer を、攻撃役として attacker というロールを想定します。 ギャザリングを作成するときに各ロールの募集人数を設定します。 ギャザリングの検索時に自分のロールに設定することで、ロールに関して空きのあるギャザリングだけが参加可能なギャザリングとして処理されます。

募集ロールにはエイリアスを設定することもできます。 例えば、 tank を更に具体的なロールで表現し、 paladinwarriordark_knight のいずれかとしてギャザリングの検索を行うとします。 ギャザリングを作成するときに、 tank のエイリアスに paladindark_knight を指定した場合、 warrior は参加できないギャザリングが作成できます。

マッチメイキング完了後に、1名が離脱し 1名だけ補充したいときに使用します。 このときに使用するのがパーティトークンです。パーティトークンを発行するにはパーティを編成するプレイヤーのプレイヤートークンです。 プレイヤートークンはプレイヤー自身が自分の代わりにパーティの代表者がマッチメイキングを行うことを許可するトークンで、3分間の有効期限があります。 パーティメンバーはそれぞれ、プレイヤートークンを発行するAPIに依頼をしてプレイヤートークンを入手し、パーティの代表者に送信します。 パーティの代表者はパーティメンバーからプレイヤートークンを受け取り、3分以内にパーティトークン発行APIに送信することで、パーティトークンを入手できます。 パーティトークンには10分の有効期限があり、10分以内にパーティトークンを使用してギャザリング作成処理または、ギャザリング検索処理を呼び出します。 こうすることで、パーティメンバー全員が参加した状態のギャザリングを作成、またはパーティメンバー全員が参加できるギャザリングに参加します。

4 vs 4 で対戦するゲームで、事前に編成したパーティを敵味方に分散することなく対戦したいことがあります。 たとえば、事前に3人で編成したパーティと、事前に4人で編成したパーティ、そして1人の野良プレイヤーをマッチメイキングして、 事前に3人で編成したパーティ + 1人の野良プレイヤー vs 事前に4人で編成したパーティ という対戦を実現したいとします。 このようなケースでは、まずは4人のマッチメイキングを実行します。 すると、3人で編成したパーティ + 1人の野良プレイヤー事前に4人で編成したパーティ の2つのギャザリングができます。 その後、それぞれのパーティの代表者が 定員2人のマッチメイキングをおこない、パーティ同士がマッチメイキングされます。 こうすることで 事前に3人で編成したパーティ + 1人の野良プレイヤー vs 事前に4人で編成したパーティ を実現できます。

マッチメイキングが完了していない状態でプレイヤー間のやりとりを必要とすることがあります。 GS2-Matchmaking では、ギャザリングの作成時にプレイヤー間の通信をする手段として2種類の方法を提供します。

募集が終わっていない状態でも、プレイヤー間のでメタデータを低頻度で交換したい場合は前者を、 募集しながらNPCを交えたり人数が不足した状態でゲームを遊ばせたい場合は後者を使用します。

低頻度・高頻度の判断基準として使用できるのが GS2-Chat の持つ制限です。 GS2-Chat は1つのチャットルームに対して秒間3回しか発言ができません。この頻度を超える場合は GS2-Realtime を使用してください。

マッチメイキングが完了したときに GS2-Gateway を使用したゲーム内プッシュ通知GS2-JobQueue によるジョブ登録 でプレイヤーにマッチメイキングの完了を知らせることができます。 また、GS2-Script を使用して任意のスクリプトを実行することもできます。 GS2-Realtime を使用してマッチメイキング後の対戦・協力プレイを実現する場合は、マッチメイキング完了後に実行される GS2-Script で GS2-Realtime のギャザリングを作成し、そのギャザリングのIPアドレス・ポートの情報を GS2-Gateway を使用したゲーム内プッシュ通知GS2-JobQueue によるジョブ登録 を使用して通知することで、ゲームサーバに誘導できます。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

マルチプレイヤーゲームを実現するには 対戦相手や協力プレイの相手を見つける 仕組みが必要です。 GS2 ではこの仕組みを実現するためのサービスとして、GS2-Matchmaking を提供しています。

一般的にマッチメイキングのアプローチは2種類存在します。

GS2 では、後者の自動マッチメイキングのみを提供しています。 手動マッチメイキングは、よりゲームプレイヤーのニーズに合ったルームを見つけられる利点はあるものの 一覧取得参加 のアクションの間に 人間による選別 というタイムラグが発生するため 参加しようとした部屋が満室になっていた という状態に陥りやすく、UX設計が非常に難しい一方で、手動マッチメイキングを行う必要があるほど厳密に対戦相手を探したいユースケースは多くないためです。

ギャザリング

GS2-Matchmaking では、マッチメイキング条件の見合うゲームプレイヤー同士を引き合わせて ギャザリング を構築します。 ギャザリングはルームのようなものと考えて問題ありません。 ギャザリングはホストとなるプレイヤーが最初に作成し、ゲストは条件の見合うギャザリングへ割り当てられます。 ギャザリング内のゲームプレイヤーが規定人数に達すると、マッチメイキングが成立したとして通知の送信やスクリプトの実行が行われ、ギャザリングは消去されます。

条件の設定

属性値

マッチメイキング条件には属性値を最大5つ指定できます。 属性値は整数値で、最小値と最大値を指定できます。対戦相手を探す際にはすべての属性値が希望する範囲に含まれるゲームプレイヤーを探します。

ロール

役割に応じたマッチメイキングを実現するときに使用します。 役割とは 盾役 回復役 攻撃役 のような分類で、マッチメイキング条件として 盾役を1人 回復役を1人 攻撃役を2人 といった形で指定できます。

ロールのエイリアス

ロールにはエイリアス(別名)を設定できます。 たとえば、役割としては 盾役 ではあるものの、ゲーム内の職業としては 戦士ナイト があったとします。 どうしても対戦相手として参加してきてほしい職業は 戦士 であってほしい。という場合に使用できるのがエイリアスです。

自分の役割として直接 盾役 と申告するのではなく 戦士 ナイト という職業レベルで申告するようにしておき、一般的なマッチメイキングでは 盾役 のエイリアスには 戦士 ナイト を設定しておきます。 すると、 戦士 でも ナイト でも 盾役 として参加できるギャザリングが出来上がります。 どうしても 戦士 しかマッチメイキングしてほしくない場合は、エイリアスに 戦士 のみを含めます。 すると ナイト盾役 として認識されなくなりますので、マッチメイキング対象から外されます。

マッチメイキング条件を緩めていく

条件が厳密であれば厳密であるほど良質なマッチメイキングとなります。 たとえば、レーティングをマッチメイキング条件に設定する場合、まったく同じレーティング値であればあるほど良質なマッチメイキングといえるでしょう。 一方で、良質なマッチメイキングを実現するにはたくさんのゲームプレイヤーが必要です。なぜならそんなに都合よくスキルが拮抗するゲームプレイヤーはいないからです。

だからといって、最初から良質なマッチメイキングをあきらめて、マッチメイキング条件として使用するレーティングの幅を大きくとる必要はありません。

GS2-Matchmaking ではギャザリング開始から1分ごとにスクリプトを実行できるようにしています。 この機能を利用すれば待ち時間に応じてマッチメイキングの条件を緩和していくことができます。 これによって、相手がいる場合は良質なマッチメイキングを、そうでない場合はとりあえず対戦相手を見つけるよう設計することができます。

フレンドのみ参加可能なギャザリング

ギャザリングには参加可能なユーザIDを列挙することで、参加者に制限をかけることができます。 この機能を利用することで、フレンドのみが参加可能なマッチメイキングを実現することができます。

ブラックリスト

GS2-Matchmaking にはブラックリストの機能があります。 マッチメイキングの条件が見合っていても、自分のユーザIDがブラックリストに含まれているゲームプレイヤーは、そのギャザリングには参加できなくなります。 ブラックリストの情報は各プレイヤーが持てるようになっており、ギャザリングに参加している全プレイヤーのブラックリストがマージされたものがギャザリングのブラックリストとして使用されます。

パーティトークンとプレイヤートークン

1つのギャザリングへ複数のプレイヤーが一緒に参加するために、 パーティトークン が使用できます。 パーティトークンを利用することで、複数のプレイヤーが一緒にギャザリングを作成したり、一緒に同じギャザリングへ参加したりできます。

パーティトークンは、パーティの代表者が、パーティ内の各プレイヤーから プレイヤートークン を集めて作成します。 プレイヤートークンは3分、パーティートークンは10分の有効期限があります。

追加募集

一度マッチメイキングが完了したものの、何らかの理由で1名が離脱し再度募集を募りたいことがあります。 このような場合、残ったメンバーでパーティトークンを作成し、再度マッチメイキングを行うことで欠員を補充する追加募集を実現することができます。

パーティ同士のマッチメイキング

ゲームの仕様によっては 4vs4 のようなチーム戦を行うことを希望するかもしれません。 このようなケースにおいて、フレンド同士をチームにしたいという仕様もあるでしょう。 GS2-Matchmaking を使ってこのような仕様を実現するには、一旦4人でマッチメイキングを実行してチームを作成します。 この際、フレンド同士のチームはフレンド限定のマッチメイキングで作成します。 その後、各チームの代表者が2人のマッチメイキングを実行して、 4vs4 の対戦相手となるギャザリングを発見するように設計します。

マッチメイキング中のプレイヤー間通信

マッチメイキングが終わっていない状態でもプレイヤー間でメッセージングを行いたいことがあります。 このような時に使用できるのが GS2-Chat / GS2-Realtime 連携です。 この機能を利用すると、 ギャザリング作成時 または マッチメイキング完了時 に GS2-Chat または GS2-Realtime のルームを作成することができます。 今回の場合は ギャザリング作成時 にルームを作成することで、マッチメイキング実行中のメッセージングに使用できます。

GS2-Chat と GS2-Realtime のどちらを使用するべきかを判断するにはいくつかの指標がありますが、マッチメイキング完了後の対戦で GS2-Realtime を利用するのであれば、マッチメイキング中のコミュニケーションにも GS2-Realtime を使うのが実装の手間は少なく済むでしょう。 もう一つの指標は通信間隔です。GS2-Chat は 1つのルームに対するメッセージの送信は秒間3回まで という制約がありますので、これを超える頻度の通信が必要なら GS2-Realtime を使うことになります。 最後の指標はコストです。GS2-Chat は 一般的なAPIリクエスト回数 による課金ですが、GS2-Realtime はルームの維持時間1分当たり+ネットワーク通信量の課金で、APIリクエスト回数には費用は発生しません。

この辺りを材料に自分のゲームにとってどの方法で仕様を実現するのがいいかを検討してみてください。

マッチメイキングの進捗のハンドリング

GS2-Realtime はマッチメイキングの進捗を GS2-Gateway によるプッシュ通知でハンドリングすることができるようになっています。 通知の種類は以下のものが用意されています。

マッチメイキングが完了したときは GS2-Gateway による通知のほかに、GS2-JobQueue を使用したハンドリングと、GS2-Script を使用したハンドリングにも対応しています。

GS2-Realtime との連携機能を使用すると ギャザリングの作成時 または マッチメイキング完了時 にルームの作成リクエストが自動的に発行され、ルームの作成が完了すると GS2-Gateway による通知が届きます。 通知には起動したゲームサーバのIPアドレスおよび待ち受けポート。通信パケットの暗号化に使用する暗号鍵などの情報が含まれており、それらの情報を使用して対戦に引き継げるようになっています。

ギャザリングの作成

ギャザリングの作成例(Unity)

yield return gs2.Matchmaking.CreateGathering(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.GatheringId); // string ギャザリング
            Debug.Log(r.Result.Item.Name); // string ギャザリング名
            Debug.Log(r.Result.Item.AttributeRanges); // list[AttributeRange] 募集条件
            Debug.Log(r.Result.Item.CapacityOfRoles); // list[CapacityOfRole] 参加者
            Debug.Log(r.Result.Item.AllowUserIds); // list[string] 参加を許可するユーザIDリスト
            Debug.Log(r.Result.Item.Metadata); // string メタデータ
            Debug.Log(r.Result.Item.CreatedAt); // long 作成日時
            Debug.Log(r.Result.Item.UpdatedAt); // long 最終更新日時
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    player,   //  自身のプレイヤー情報
    capacityOfRoles,   //  参加者
    allowUserIds,   //  参加を許可するユーザIDリスト
    attributeRanges   //  募集条件(オプション値)
);

ギャザリングを作成するためには 募集条件参加可能なユーザIDリスト を設定する必要があります。 募集条件は 属性値募集人数 の2種類があります。

属性値

属性値のモデル構造

パラメータ データ型    必須  説明
name    string  true    属性名
min     integer true    ギャザリング参加可能な属性値の最小値
max     integer true    ギャザリング参加可能な属性値の最大値

最大5つの属性値を指定します。属性値は整数値の範囲で指定できるようになっています。 ゲームプレイヤーがマッチメイキングリクエストを出す際には自分の属性値の値を申告し、属性値の範囲に該当するギャザリングが参加候補のギャザリングとして判定されます。

募集条件

募集条件モデル構造

パラメータ         データ型            必須  説明
roleName        string          true    ロール名
roleAliases     list[string]    false   ロール名の別名リスト
capacity        integer         true    募集人数
participants    list[Player]    true    参加者のプレイヤー情報リスト

募集人数は文字通り何人のゲームプレイヤーを見つけるかというパラメータです。 募集人数は 役割 ごとに設定できます。 役割 とは 盾役1人 回復役1人 攻撃役2人 というように設定できます。 特にこだわりがない場合は1つの役割だけ指定し、募集人数の値だけ埋めてギャザリングの作成を行うことになります。

マッチメイキングの実行

すでに存在するギャザリングの中で自分が参加可能なギャザリングを見つけて参加を行います。 マッチメイキングAPIは一定時間経過しても参加可能なギャザリングが見つからず、また全てのギャザリングの走査が終わっていない場合は コンテキストトークン を応答します。 コンテキストトークン はマッチメイキング処理を再開するために必要となる情報を文字列化したもので、マッチメイキングAPIの呼び出し時に指定すると、マッチメイキング処理を再開できます。 最後まで処理を実行したにも関わらず参加可能なギャザリングを見つけられなかった時には null を返しますので、その応答をもってギャザリングの作成処理を行うのがいいでしょう。

マッチメイキングリクエスト例(Unity)

yield return gs2.Matchmaking.DoMatchmaking(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.GatheringId); // string ギャザリング
            Debug.Log(r.Result.Item.Name); // string ギャザリング名
            Debug.Log(r.Result.Item.AttributeRanges); // list[AttributeRange] 募集条件
            Debug.Log(r.Result.Item.CapacityOfRoles); // list[CapacityOfRole] 参加者
            Debug.Log(r.Result.Item.AllowUserIds); // list[string] 参加を許可するユーザIDリスト
            Debug.Log(r.Result.Item.Metadata); // string メタデータ
            Debug.Log(r.Result.Item.CreatedAt); // long 作成日時
            Debug.Log(r.Result.Item.UpdatedAt); // long 最終更新日時
            Debug.Log(r.Result.MatchmakingContextToken); // string マッチメイキングの状態を保持するトークン
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    player,   //  自身のプレイヤー情報
    matchmakingContextToken   //  検索の再開に使用する マッチメイキングの状態を保持するトークン(オプション値)
);

マッチメイキングの中断

すでにいずれかのギャザリングに参加した状態で、ギャザリングから離脱したいときに使用します。

マッチメイキングキャンセル例(Unity)

yield return gs2.Matchmaking.CancelMatchmaking(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.GatheringId); // string ギャザリング
            Debug.Log(r.Result.Item.Name); // string ギャザリング名
            Debug.Log(r.Result.Item.AttributeRanges); // list[AttributeRange] 募集条件
            Debug.Log(r.Result.Item.CapacityOfRoles); // list[CapacityOfRole] 参加者
            Debug.Log(r.Result.Item.AllowUserIds); // list[string] 参加を許可するユーザIDリスト
            Debug.Log(r.Result.Item.Metadata); // string メタデータ
            Debug.Log(r.Result.Item.CreatedAt); // long 作成日時
            Debug.Log(r.Result.Item.UpdatedAt); // long 最終更新日時
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    gatheringName   //  ギャザリング名
);

レーティング

同じレベル帯でのマッチングを実現するためにギャザリングの属性値にGS2Macthmakingで提供するレーティングを使用することができます。 レーティングを使用するにあたって偽りのない勝敗結果をもとにレーティングを計算する必要があります。 ゲームサーバーで勝敗が判断できる場合は、ゲームサーバーが勝敗結果を報告すれば問題ありません。 またGS2Realtimeからも勝敗結果の報告が可能になる予定です。 一方でP2P対戦などクライアントが勝敗結果を報告する場合、勝敗を偽るチート行為を対策する必要があります。 そこでGS2Macthmakingではクライアントが勝敗結果を投票するという方法を用意しています。

投票用紙と投票

対戦に参加したクライアントは投票用紙と各プレイヤーの勝敗・順位を投票します。 GS2Macthmakingは投票結果の多数決で勝敗・順位を判断しレーティングを計算します。 このように各クライアントが別々にGS2Macthmakingに投票してもいいですが、投票が集まりレーティングが計算されるタイミングをクライアント側で把握できません。 そこで勝利したクライアントの一つを代表とし、各クライアントの投票用紙を代表クライアントに集め、 過半数の投票用紙がそろったタイミングでGS2Macthmakingへ勝敗結果を投票、同時にその通知を代表クライアントから各クライアントに通知する方法を推奨します。 『勝利したクライアント』としているのは、敗北した側が自分たちが勝ったことにして報告することにインセンティブはありますが、その逆はないためです。 負けた側が投票用紙を渡してこない可能性がありますが、その場合も過半数の投票用紙があれば結果を通すことができます。

投票が成立しない可能性

チート対策として勝敗結果を投票する方式ご紹介しましたが、チート行為を完全に排除することはできません。 例えば1対1の場合は片方が偽りの勝敗を報告をすれば正しい勝敗を判断できません。 対戦人数が増えればその分信用度は増していきますが、正しい投票が成立しない可能性は完全にはなくなりません。 対戦人数が少人数である場合や完全なチート対策をする場合は、ゲームサーバーの構築を検討してください。

GS2-Mission

サービス概要

ミッション機能を提供するサービスです。

ミッション機能は「n回 クエストをクリアする」「n体のキャラクターを入手する」のような条件を設定し、達成することで報酬が得られる仕組みです。 これを実現するために ”ミッションの条件設定” ”カウンターの購読” ”カウンターの上昇” という仕組みを使います。

ミッションの条件設定とは、ミッションが達成されたことになるカウンターの閾値を設定するものです。

カウンターの購読とは、ミッションの対象となるカウンターの設定です。 1つのカウンターは複数のミッションから購読することができ、ミッションごとに異なるリセットタイミングを設定できます。 たとえば、「クエストを通算1000回クリアした」というミッションと、「クエストを今日10回クリアした」というデイリーミッションを作りたい場合、 クエストをクリアするごとにカウントアップされる1つのカウンターを両方のミッションから購読し、前者には 'リセットなし' 、後者には '毎日' のリセットタイミングを設定することで、1回のカウンター操作で複数の条件のミッションを処理することができます。

カウンターの上昇 は文字通りカウンターを上昇させる操作で、例えばクエストをクリアしたときにクエストのクリア回数のカウンター上昇を報酬に含めて使用します。

ミッションには2つの期間を設定できます。 1つ目はカウンターを操作できる期間で、カウンターを上昇させるのをイベント開催期間に限定するようなケースで使用します。 2つ目はミッション達成報酬の受け取り可能期間で、イベントが終わった後もしばらくミッションの報酬だけは受け取れるようにしたい場合は2つの期間を別に設定して使用します。 期間の指定には GS2-Schedule のイベントを関連付けます。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

同一カウンターに対する操作は1秒間に3回までにおさえてください。 異なるユーザや、同一ユーザでも異なるカウンターに対する処理であればこの制限はありません。

基本的な使い方

使い方は3ステップです。

  1. マスターの作成
  2. カウンターの増加
  3. ミッション報酬の受け取り

マスターの作成

マネージメントコンソールで作成します。 作成するマスターは'カウンター' と'ミッショングループ' 、また'ミッショングループ' の中で設定する'タスク' です。

カウンター

ミッションを達成したかどうかを判定するためカウンターです。 例えば10回対戦するミッションであれば対戦完了時に対戦回数をカウントアップします。 カウンターは定期的(毎日・毎週・毎月)にリセットすることもできます。 デイリーミッションなどを実現する場合に設定してください。

またGS2-Scheduleと連携してイベント中のみカウントアップできるカウンターの作成も可能です。 こちらはGS2-Scheduleのページをご確認ください。

ミッショングループ

ミッショングループとは個々のミッションを束ねる役割をします。 ミッショングループにはミッションのリセットタイミングを設定できます。 例えばリセットタイミング別に、デイリーミッショングループ、ウィークリーミッショングループ、無期限ミッショングループを作り、それぞれのミッショングループにミッション登録することで管理が容易にできます。

タスク

GS2では個々のミッションのことをタスクと呼んでいます。ミッショングループの中に登録していきます。 この時、タスク達成の条件として作成したカウンターとそのカウンターの目標値を設定します。 次に報酬を設定します。この報酬でも任意のカウンターを増加させることができ、例えばデイリーミッションを3つ達成する、といったタスクを作ることもできます。

カウンターの増加

カウンターの増加のAPIはクライアントからは、ユーザー用のセキュリティポリシーであるApplicationAccessでは実行出来ません。 これは不正にカウンターを増加させるチート行為を出来なくするためです。

カウンター増加の方法としては3つあります。

スタンプシートの報酬として設定する

例えばマネージメントコンソールでGS2-Questのクエストモデルマスター開いてみてください。 その中のクエストクリア時の報酬に「Mission:カウンターに加算」があります。 この場合はクエストクリア回数カウンターの増加方法として使えます。 他のサービスからもカウンターの加算ができますので、適した方法を探してください。

GS2Scriptで増加させる

GS2イベントの報酬以外の方法でカウンターを増加させたい場合も考えられます。例えばログイン回数カウンターです。 この場合は、カウンターを増加させるGS2-Scriptを書いてGS2-Acountのネームスペースでログイン時に実行する設定をすることで実現できます。 GS2-Scriptもご確認ください。

サーバーからAPIを呼び出す

サーバーからカウンターを増加させる例(Python)

from gs2_mission_client.request import IncreaseCounterByUserIdRequest
from gs2_mission_client.result import IncreaseCounterByUserIdResult

result = client.increase_counter_by_user_id(
    IncreaseCounterByUserIdRequest()\
        .with_namespace_name(namespace_name)\
        .with_counter_name(counter_name)\
        .with_user_id(user_id)\
        .with_value(value)
)

自作されているサーバーからAPIを呼び出してカウンターを増加させることもできます。

ミッション報酬の受け取り

ミッションの報酬を受け取る例(Unity)

yield return gs2.Mission.ReceiveRewards(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.StampSheet); // string ミッションの達成報酬を受領するスタンプシート
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    missionGroupName,   //  ミッショングループ名
    missionTaskName,   //  タスク名
);

ミッションを達成したらミッション達成報酬を取得します。 ここで注意すべきは、ミッション達成報酬を取得だけでは報酬は得られません。 ミッションの報酬が1つである場合はスタンプシートの実行を、2つ以上である場合はGS2-JobQueueを使用する必要があります。 スタンプシートについては はじめかた⇒スタンプシートのページをご確認ください。 GS2-JobQueueについてはGS2-JobQueueのページをご確認ください。

GS2-Money

サービス概要

課金通貨を管理するサービスです。

課金通貨とは、日本の資金決済法に定義された、前払式支払手段 (自家型) に該当するゲーム内通貨を指します。 資金決済法に準拠するために、GS2-Money では、残高や通貨のトランザクションの管理を行います。

異なるプラットフォーム間でウォレットを共有したくない場合、アクセス元のプラットフォームによって同一アカウント内のウォレットを分ける仕組みも提供します。 その場合でも、無償提供分は、異なるプラットフォーム間で共有することができます。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

通常のAPI利用料金に加えて流通額に対するレベニューシェアが適用されます。

月間流通額の範囲 レベニュー
¥0 〜 ¥999,999 10%
¥1,000,000 〜 ¥9,999,999 5%
¥10,000,000 〜 ¥99,999,999 3%
¥100,000,000 〜 ¥999,999,999 1%
¥1,000,000,000 〜 ¥100,000,000,000 0%

レベニューシェアに対しては通常の無料枠の適用はありませんが、月間の流通額が 10,000円 に満たない場合は例外として利用料金を頂戴しません。

制限・制約

同一ウォレットに対する操作は1秒間に3回までにおさえてください。 異なるユーザや、同一ユーザでも異なるウォレットに対する処理であればこの制限はありません。

基本的な使い方

ゲームの収益化の方法は大きく3種類あります。

この中でもアプリ内課金を使って収益化を実現するために必要となる機能を提供するのが GS2-Money です。 GS2-Money はゲーム内で課金通貨を扱うために必要な機能が一通り実装されています。

課金通貨とは

課金通貨は、ゲーム内通貨の中でも、現金を使って購入できる通貨を指します。 現金を使って購入した通貨は、日本国内において 資金決済に関する法律 通称 資金決済法 の制約を受け、その規定に従った管理をおこなう必要があります。

資金決済法

電子決済に関する法律で、ゲーム内の通貨は 前払式支払手段 に該当することが一般的です。 前払式支払手段 には 自家型第三者型 がありますが、自社で発行した通貨を自社で使用する場合は 自家型 となり、ゲーム内の通貨は 前払式支払手段(自家型) に該当することが一般的です。 ※ 実際自分のタイトルのゲーム内通貨がどの方式に該当するかは法律の専門家にご相談ください。

GS2-Money の機能

GS2-Money は『前払式支払手段(自家型)』の法的要件を満たすよう設計されています。 具体的には以下の機能を有しています。

なお、 GS2-Money は課金通貨の無料付与分も統合的に管理できます。これにより、通貨の消費時には、ユーザーが有料で購入した通貨と、無料で入手した通貨を、自動で合算して使用することが可能です。

通貨の対現金単価

GS2-Money では、通貨の入手ごとに、現金に対する単価を管理します。 たとえば、200円でゲーム内通貨を 100 入手したあと、100円でゲーム内通貨を 100 入手した場合、 GS2-Money では対現金単価 1.5 のゲーム内通貨を 200 持っていると扱うのではなく、対現金単価 2 のゲーム内通貨と対現金単価 1 のゲーム内通貨をそれぞれ 100 持っているものとして管理します。無料入手分は、対現金単価 0 として扱われます。 また、ゲーム内通貨の消費時にも、どの対現金単価のゲーム内通貨がどれだけ消費され、どの対現金単価のゲーム内通貨がどれだけ残っているかが管理されます。

通貨の消費優先度

GS2-Money の内部では対現金単価の異なるゲーム内通貨が区別して管理されますが、消費の際に個別の所持量を意識する必要はありません。 たとえば、対現金単価 1 のゲーム内通貨だけで 100 持っている場合でも、対現金単価 1 と 2 のゲーム内通貨をあわせて 100 持っている場合でも、その違いを意識せずにそこからゲーム内通貨を 100 消費することができます。 異なる対現金単価のゲーム内通貨を複数持っている場合に、どこから優先して消費するかは、以下のポリシーから選択できます。

レシートの記録

GS2-Money は決済プラットフォームごとのレシートを検証し、使用済みのレシートを記録する機能が用意されています。 現在対応しているプラットフォームは以下です。

近日対応予定のプラットフォームは以下です

通貨の入手

セキュリティに関する注意事項

課金通貨の入手はきわめてセンシティブな操作です。 なぜなら、ゲーム性やゲーム内経済に影響を与えるだけでなく、現金的価値を有し、その管理について資金決済法の制約を受けるユーザ資産を増加させる操作だからです。 課金通貨の入手に関してクライアントから任意の操作を受け付けることは、その現金的価値を不正に増殖させることになりかねません。

そこで、GS2 ではスタンプシートの報酬としてしか課金通貨の入手を行えないようにしています。 スタンプシートの報酬の内容はサーバに定義を持ち、また報酬を得る前にゲーム内ストアでの購入処理などをおこなったことをスタンプシートの仕組みが保証するため、課金通貨の不正な増殖を防げます。 したがって、課金通貨の入手には、ゲーム内ストアでの購入や、クエストの報酬として入手するような報酬設計が必要です。

通貨の消費

通貨の消費例(Unity)

yield return gs2.Money.Withdraw(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.Slot); // integer スロット番号
            Debug.Log(r.Result.Item.Paid); // integer 有償課金通貨所持量
            Debug.Log(r.Result.Item.Free); // integer 無償課金通貨所持量
            Debug.Log(r.Result.Item.UpdatedAt); // long 最終更新日時
            Debug.Log(r.Result.Price); // float 消費した通貨の価格
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペースの名前
    slot,   //  スロット番号
    count,   //  消費する課金通貨の数量
    paidOnly   //  有償課金通貨のみを対象とするか
);

GS2では通貨の消費に関しても GS2-ShowcaseGS2-Exchange を利用して対価の交換と報酬の付与で表現することを推奨しています。 しかし、サーバで管理しない報酬を付与する場合にも利用できるよう、通貨の消費はAPIで実行できるようになっています。

二次通貨の管理

GS2-Money は二次通貨の取り扱いにも対応しています。 二次通貨とは、課金通貨と引き換えに入手したアイテムのことで、資金決済法の解釈によっては、これらも、直接現金と引き換えに入手した課金通貨に準じた扱いを求められる可能性があります。 たとえば、100円相当の課金通貨でスタミナドリンクを購入した場合、そのスタミナドリンクもまた、継承的に100円相当の価値を持つ課金通貨であるとも考えられるためです。 GS2 では、 GS2-Showcase や GS2-Exchange で対価に GS2-Money の課金通貨(上記の例では、ゲーム内通貨)を設定し、報酬にも GS2-Money の課金通貨(上記の例では、スタミナドリンク)を設定すると、課金通貨の種類をまたいでその価値を引き継げるようになっています。

TIPS

現金で課金通貨を購入する

月額サブスクリプションを実現する

事業者としてやらなければならないこと

3月31日/9月30日時点でゲーム内通貨の未使用残高が1,000万円を超えた段階で、該当ゲーム内通貨は資金決済法の対象となります。 それにあたって、GS2だけでなく、GS2を利用する事業者にも一定の責任が発生します。 どのような責任が発生するのか、詳しくは専門家にご相談いただきたいと思いますが、代表的なものを記載します。

コンプライアンス
利用者保護

GS2のサービスは Amazon Web Services および Google Cloud Platform を利用して提供されます。 これらの事業者は ISO 27001(セキュリティ) ISO 27018(個人情報保護) を始めとした認証を取得し、適切に運営されています。 GS2のマネージメントコンソールやAPIから取得したデータの保護に関しては事業者の責任で行う必要があります

苦情処理体制
事務運営

GS2-News

サービス概要

お知らせ機能を実現するサービスです。

お知らせで配信する記事データは Hugo(https://gohugo.io/) で作成されている必要があります。 GS2-News に Hugo のサイトデータ一式を zip で圧縮したデータをアップロードするか、GitHub のリポジトリを指定して反映します。 サイトデータは全体で100MB以内に収める必要があります。

GS2-News は受け取ったサイトデータから /content/{sectionName}/{contentName}/index.html を走査します。 index.* の Front Matter を解析し、公開期間などの情報を抽出します。そのため、サイトデータのツリー構造はこの形式に従っている必要があり、 コンテンツの上部に記述する Front Matter は必ず yaml 形式で記述する必要があります。

Front Matter にはいくつかのGS2に向けた制御構文を記述することができます。 詳細は後述しますが、コンテンツの公開条件を Front Matter の制御構文で定義した場合、GS2-News は公開条件を満たさないコンテンツを削除してサイトをビルドします。 GS2-News は公開条件が設定されたコンテンツの公開・非公開状態のすべてのパターンを事前にビルドし、Webサーバに配置します。 そのため、公開条件が設定されたコンテンツが多数ある場合、組み合わせ爆発が発生し更新にかかる時間や費用が増大します。 公開条件が設定されたコンテンツが最小になるように工夫をしてください。

ビルドが行われるパターン数はサイトデータのアップロード時の戻り値で確認することができます。

クライアントが自身にとって現在有効なサイトデータを取得する方法として複数の方法が提供されます。

サイトのビルドには 『-D, --buildDrafts』 オプションは指定しません。 たとえ、サイトデータ内にコンテンツがあったとしても Front Matter で draft として宣言されたコンテンツは配信されません。

Front Matter に記述可能な制御構文

公開期間の設定

x_gs2_scheduleEventId: ${GS2-Schedule のイベントGRN}

と記述することで、そのコンテンツは該当イベントの開催期間にしか公開されなくなります。 イベントに連動したコンテンツの配信に利用できます。

また、GRNには {region}{ownerId} のプレースホルダを使用でき、それぞれ実行中のリージョン・オーナーIDに置換されます。

grn:gs2:{region}:{ownerId}:schedule:schedule-0001:event:event-0001
## 利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

使い方は2ステップです。

  1. 記事を作成する
  2. 記事を閲覧する

記事を作成する

以下のリンクにサンプルと解説があります。

https://github.com/gs2io/gs2-news-sample

作成した記事はマネージメントコンソールから登録します。

実際に作成を始める前にサンプルをマネージメントコンソールから登録し、手順2でアクセスできるか試しておくといいでしょう。

記事を閲覧する

記事のURLを取得する例(Unity)

yield return gs2.News.GetContentsUrl(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Items); // list[SetCookieRequestEntry] お知らせコンテンツにアクセスするために設定の必要なクッキー のリスト
            Debug.Log(r.Result.BrowserUrl); // string お知らせコンテンツにアクセスするためのURL
            Debug.Log(r.Result.ZipUrl); // string ZIP形式のお知らせコンテンツにアクセスするためのURL Cookieの設定は不要
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペースの名前
);

サンプルコードで現在閲覧可能なお知らせ記事のURLを入手できます。このURLにアクセスして記事を閲覧します。

URLにアクセスする時、アクセスするために設定の必要なクッキーを使用してください。 ZIP形式のお知らせコンテンツにアクセスする場合は不要です。

GS2-Quest

サービス概要

クエストの進捗管理をします。

クエストには開始するために必要な対価、クエストに成功したときの報酬、クエストに失敗したときの報酬 を設定できます。

クエストを開始するために必要な対価にはスタミナを消費する処理や、回数制限のカウンター上昇などを設定します。

クエストに成功したときの報酬は複数設定でき、クエスト開始時に抽選する際に使用する確率を設定できます。 これを使用することで、クエストとしては同じだが、通常コンテンツとレアエネミーが出現するコンテンツを出し分けることができます。 クエスト成功時の報酬には、キャラクターの経験値やアイテム、ゲーム内通貨などを設定します。

クエストに失敗したときの報酬とは、クエストに失敗したときに開始時に受け取った対価を返却する場合などに設定します。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

クエストとはゲーム内のストーリー進行や報酬付きタスクを実現するための機能であり、GS2 ではこの機能を実現するために GS2-Quest を提供しています。

GS2-Quest で提供するのは、具体的には以下の保証です。

以下の内容については、 GS2-Quest は関知しません。

クエストモデルの登録

GS2-Quest では、クエスト内容の設定をサーバサイドで管理します。 そのため、この機能を利用するには、事前に GS2-Quest にマスターデータをアップロードしておく必要があります。

クエストのマスターデータの設定項目(GS2-Quest にはどんな機能があるのか)については、以下のドキュメントを参考にしてください。

前提クエスト

ゲーム仕様上、クエストにはシーケンシャルなアクセスを求めることが多くあります。 たとえば、2章をプレイするには1章をクリアしていなければならない、というものです。

このように、あるクエストを開始するのに、事前にクリアしている必要があるクエストを 前提クエスト と呼びます。 GS2 では、各クエストに対して前提クエストを設定でき、前提クエストのクリアフラグが立っていなければクエストを開始できないようにすることができます。

クエストの挑戦対価

クエストに挑戦するために対価を必要とするよう設定できます。 対価にはたとえば スタミナクエスト挑戦権利アイテム を設定でき、それらが足りない状態ではクエストを開始できないようにすることができます。

クエストの報酬

クエストの報酬には大きく分けて2種類が設定できます。

クリア報酬は文字通りのクエストをクリアしたときに得られる報酬です。 失敗報酬とは、クエストに失敗したときに得られる報酬で、一般的には挑戦に使用したスタミナを払い戻すような機能として用いられます。

クリア報酬のランダム化

毎回同じクリア報酬では少し味気ないかもしれません。 GS2-Quest では、複数のクリア報酬を設定し、ランダムに選択させることができます。 その際の確率は GS2-Lottery と同じく重みベースの確率設定が行えます。

クエスト報酬データにはメタデータを保存する領域も付随します。 たとえば、クリア報酬のメタデータにモンスターの出現パターンを載せておき、クリア報酬に応じたモンスターが出現するように設定するようなこともできます。

クエストの開始

クエストの開始例(Unity)

yield return gs2.Quest.Start(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.StampSheet); // string クエストの開始処理の実行に使用するスタンプシート
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  カテゴリ名
    questGroupName,   //  クエストグループ名
    questName,   //  クエストモデル名
    force,   //  すでに開始しているクエストがある場合にそれを破棄して開始するか(オプション値)
    config   //  スタンプシートの変数に適用する設定値(オプション値)
);

クエストを開始すると、内部では複数登録されたクエスト報酬から抽選を行い、報酬の内容を確定します。 つまり、GS2-Quest を使う場合、クエストを開始する時点でクリア時に得られる報酬が確定します。 これは クエストを開始後、完了するまでの間にアプリを強制終了 するなどして報酬の再抽選を行う不正行為が行えないようにするための仕様です。

クエストの開始処理のレスポンスには スタンプシート が応答されます。スタンプシートを実行するまでクエスト開始処理は保留されます。

クエストの完了

クエストの完了例(Unity)

yield return gs2.Quest.End(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.ProgressId); // string クエスト挑戦
            Debug.Log(r.Result.Item.TransactionId); // string トランザクションID
            Debug.Log(r.Result.Item.QuestModelId); // string クエストモデル
            Debug.Log(r.Result.Item.RandomSeed); // long 乱数シード
            Debug.Log(r.Result.Item.Rewards); // list[Reward] クエストで得られる報酬の上限
            Debug.Log(r.Result.StampSheet); // string 報酬付与処理の実行に使用するスタンプシート
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  カテゴリ名
    transactionId,   //  トランザクションID
    rewards,   //  実際にクエストで得た報酬(オプション値)
    isComplete,   //  クエストをクリアしたか(オプション値)
    config   //  スタンプシートの変数に適用する設定値(オプション値)
)

クエストの完了時には 実際にクエストで得た報酬 を指定できます。 指定しなかった場合は開始時に応答された報酬を全て入手します。ゲーム内で敵や宝箱を無視したことで報酬が減額される場合はここで数量を減らして報告してください。 開始時に決定された報酬より多くの報酬を得ようとしたり、得られない報酬を得ようとするとエラーになります。

クライアントがクエストの完了を呼び出せることによって、プレイヤーのレベルでは本来クリアできない難易度のステージをクリアしたと報告するチート行為の可能性があります。 これを回避するにはGS2-Identifierのセキュリティポリシー設定でクライアントからクエストの完了の呼び出せなくし、サーバーから呼び出すようにする方法があります。

クエストの完了報告のレスポンスには スタンプシート が応答されます。スタンプシートを実行するまでクエスト完了処理は保留されます。 スタンプシートについては はじめかた⇒スタンプシートのページをご確認ください。

GS2-Ranking

サービス概要

スコアやクリアタイムのランキング処理を実現します。

ランキングには全員が同じデータを参照するグローバルランキングと、 フレンド間やギルド内のランキングのようなユーザによって見えるランキングの内容の異なるスコープドランキングがあります。

グローバルランキングは、15分~24時間の間で指定した間隔でランキングの集計処理がおこなわれ、 ゲームユーザーからのリクエストは事前に集計された結果を応答します。 これによって、大量のゲームプレイヤーが居たとしてもレスポンスタイムは変わらないように設計されています。

スコープドランキングは各ゲームプレイヤーがスコアバケットをもち、購読しているゲームプレイヤーがスコアを登録するとスコアバケットにスコアが追加されます。 各ゲームプレイヤーは自分のスコアバケット内のスコアを使ってランキングを処理します。

グローバルランキング・スコープドランキング ともにユーザーID毎に保持できるスコアを1個にするか、複数保持できるかを設定できます。 ランキングを登録したときに最後に登録したスコアだけをランキング対象としたいか、登録したすべてのスコアをランキング対象としたいかで設定できます。 すべてのスコアをランキング対象とする場合、データ量が膨れ上がりやすくなります。その結果、GS2の利用料金にも影響を与えることとなります。 ゲームシステム上の大きな理由がなければ最後に登録された1つのスコアのみがランキング対象となるように設定することをお勧めします。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

使い方は3ステップです。

  1. カテゴリマスターを作成する
  2. スコアを登録する
  3. ランキングを見る

カテゴリマスターを作成する

マネージメントコンソールで作成します。 設定項目で注意する点は、特に理由がなければ「ユーザID毎にスコアを1つしか登録されないようにする」にチェックを入れることです。 ユーザーID毎に複数スコアを保存するとデータの量が膨れ上がり、利用料金の増加につながります。

スコアを登録する

クライアントから登録する例(Unity)


yield return gs2.Ranking.PutScore(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.CategoryName); // string カテゴリ名
            Debug.Log(r.Result.Item.UserId); // string ユーザID
            Debug.Log(r.Result.Item.ScorerUserId); // string スコアを獲得したユーザID
            Debug.Log(r.Result.Item.Score); // long スコア
            Debug.Log(r.Result.Item.Metadata); // string メタデータ
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    categoryName,   //  カテゴリ名
    score,   //  スコア
    metadata   //  メタデータ(オプション値)
);

サーバーから登録する例(python)


from gs2_ranking_client.request import PutScoreByUserIdRequest
from gs2_ranking_client.result import PutScoreByUserIdResult

result = client.put_score_by_user_id(
    PutScoreByUserIdRequest()\
        .with_namespace_name(namespace_name)\
        .with_category_name(category_name)\
        .with_user_id(user_id)\
        .with_score(score)\
        .with_metadata(metadata)
)

スコアの登録はユーザー用のセキュリティポリシーであるApplicationAccessではクライアントからも実行できるようになっています。 ただしランキング報酬などを用意する場合は、不正なスコアを登録するチート行為が行われるかもしれません。 これを回避する場合はクライアントからスコアの登録ができないようにセキュリティポリシーを設定します。 セキュリティポリシーの設定についてはGS2-identifierのページをご確認ください。

また自作のサーバーからスコアを登録することができます。ゲームシステムを自作のサーバーで実現し、ゲームを遊んだ結果のスコアをサーバーからGS2に登録する方法が安全です。

ランキングを見る

ランキングを取得する例(Unity)


yield return gs2.Ranking.GetRanking(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Items); // list[Ranking] ランキングのリスト
            Debug.Log(r.Result.NextPageToken); // string リストの続きを取得するためのページトークン
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    categoryName,   //  カテゴリ名
    pageToken,   //  データの取得を開始する位置を指定するトークン(オプション値)
    limit,   //  データの取得件数(オプション値)
    startIndex   //  ランキングの取得を開始するインデックス(オプション値)
);

ランキングを上位から取得します。

GS2-Realtime

サービス概要

対戦・協力プレイ機能を実現します。

ルームを作成すると、IPアドレス ポート 暗号鍵 の3つの情報が発行されます。 ルームに参加するには、発行された IPアドレス ポート に WebSocket で接続します。 その通信には発行された 暗号鍵 を使用して通信します。

同時接続数や通信頻度の制限はありません。

ルームのライフサイクル

作成

GS2-Realtime はルームの作成リクエストを受け付けてからサーバを起動します。 この時、ルームの数が規定数未満の場合は規定数に達するようホットスタンバイとなるルームを追加で起動します。 規定数の数はGS2によって自動的に調整されます。

つまり、リクエストを受け付けてからサーバを起動する コールドスタート 時と ホットスタンバイされたルームを利用する ホットスタート でルームの作成リクエストを受け付けてから実際に割り当てられるまでの時間に差が生じます。

コールドスタート時の待ち時間の目安は 40秒〜60秒 ホットスタート時の待ち時間の目安は3〜5秒です。

終了

起動されたルームは作成後5分間誰も接続に来なかった場合終了されます。 この終了処理はホットスタンバイのルームにも適用されますが、ホットスタンバイの起動時間は利用料金に加算されません。

ルームに参加するすべてのプレイヤーから無通信状態が1分間続いても自動的に終了されます。

ルームの最大起動時間は3時間です。作成から3時間が経過すると自動的に終了されます。

コールドスタートの発生条件

## 利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

ルームの起動時間1分あたりの利用料金と、データのアウトバウンド通信容量に対して費用が発生します。 ルームが1つであれば、ルームへの参加者が2人でも100人でも利用料金は変わりません。

正式サービス開始までにサーバのスペックの変更をできるようにします。 対戦人数が多い場合や、通信頻度が高い場合は高スペックなサーバを必要とする場合があります。

正式サービス開始後のマイルストーンとして、サーバサイドの実装を差し替える機能を提供予定です。 この機能が実装されると、サーバ側でロジックを定義できるようになり、パケットリレーよりも柔軟なサーバ機能を利用できるようになります。 この場合、サーバサイドのロジックの複雑さによって高スペックなサーバを必要とする場合があります。

現在利用可能なものは realtime1.nano のみです。

スペック 1分あたりの利用料金
realtime1.nano 0.04円
realtime1.micro 0.06円
realtime1.small 0.12円
realtime1.medium 0.24円
realtime1.large 0.5円

データ転送容量(アウトバウンド)

15円/1GB


コールドスタート が発生するのを許容できない場合は 1ゲームサーバあたり月額1500円+税(最低契約台数5台/最低契約期間1年) にてホットスタンバイを用意することが可能です。 詳細はお問い合わせください。

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

GS2-Schedule

サービス概要

ゲーム内のイベントの予定を管理します。

このサービスを単独で使うことはなく、 GS2-Showcase や GS2-Quest などと連携して、イベント開催期間のみストアに陳列する商品やクエストを実現します。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

使い方は2ステップです。

  1. イベントマスターを作成する
  2. 各サービスから利用する

イベントマスターを作成する

サーバーからトリガーを引く例(python)


from gs2_schedule_client.request import TriggerByUserIdRequest
from gs2_schedule_client.result import TriggerByUserIdResult

result = client.trigger_by_user_id(
    TriggerByUserIdRequest()\
        .with_namespace_name('schedule-0002')\
        .with_trigger_name('trigger1')\
        .with_user_id('user-0001')\
        .with_trigger_strategy('renew')\
        .with_ttl(ttl)
)

マネージメントコンソールから作成します。 作成の際の注意点として、イベントの期間の種類が「固定時間」と「プレイヤー別期間」が選べます。

固定時間の場合は指定した日時が来れば全てのプレイヤーも平等に訪れます。

プレイヤー別期間の場合は開始のトリガーを引く必要があります。トリガーの引き方は自作のサーバーからAPIを実行するか、GS2-Scriptを使う方法があります。

各サービスから利用する

例えばマネージメントコンソールからGS2-Questのクエストグループモデルマスターを見てください。 挑戦可能期間の設定から作成したイベントを指定できます。 こうすることでイベント期間中だけ挑戦できるクエストを実現できます。

他にもGS2-Showcaseと組み合わせることで期間限定商品などを作れます。

GS2-Script

サービス概要

ゲーム固有の仕様を実現するためのサービス。

GS2内の様々なイベントをトリガーとしてスクリプトを実行できます。 例えば、アカウントの登録をしたときのイベントをトリガーとして、アカウントの初期設定スクリプトを実行したり、 プレイヤーのレベルアップイベントをトリガーとして、スタミナを回復するスクリプトを実行したり、 ゲームの仕様を標準のGS2の機能で実現できないときにスクリプトを使用して機能を拡張できます。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

開発側ですること

例えばGS2-Accountのネームスペース情報を見ると、アカウント作成時と認証時に実行するスクリプトを設定することができます。

ゲームプレイヤー側ですること

GS2-JobQueueの経由

GS2スクリプトを各サービスのネームスペースに設定する際、GS2-JobQueueのネームスペースを任意で指定することができます。 指定した場合、スクリプトはすぐ実行されず一旦ジョブとしてGS2-JobQueueに登録してから実行することができます。 GS2-JobQueueを経由する利点は、ジョブの実行に失敗した場合に一定回数までリトライできること、一定回数以上失敗したジョブはデッドレタージョブとして記録が残ること、APIの応答速度が落ちづらいことなどがあります。 詳しくはGS2-JobQueueを確認してください。

スクリプト実行結果の確認方法

GS2-Scriptに限らず、スクリプトやAPI呼び出しの実行結果を確認するにはGS2-Logを使う必要があります。

スクリプトはゲームプレイヤーの行動(API呼び出し)を契機に実行されますが、API呼び出しの返り値にスクリプトの実行結果は含まれません。 ゲームプレイヤー側でスクリプトの実行結果を確認する必要がある場合はGS2-JobQueueを経由することで確認できます。

スクリプトサンプル

通貨を増やす

client = gs2('money')
api_result = client.deposit_by_user_id({
    namespaceName='money',
    userId=args['account']['userId'],
    slot=0,
    price=0,
    count=10000,
})

if(api_result['isError']) then
    fail(api_result['statusCode'], api_result['errorMessage'])
end

result = api_result['result']

サンプルとしてアカウント作成完了時に初期ゲーム内通貨10000を付与するスクリプトを記載します。 作成されたアカウント(userId)に通貨を付与するため引数(args)を使用しています。契機によって使用できる引数は変化します。引数のサンプルはコンソールのスクリプト更新ページで確認できます。 また他のスクリプトのサンプルコードはGS2-SDKの各サービス内のGS2-Scriptタブで確認できます。

GS2-Showcase

サービス概要

ゲーム内ストア機能を提供します。

販売する商品には対価と報酬を設定します。対価にも報酬にも複数のリソースを設定できます。

ステップガチャや、初回のみディスカウントといった仕組みを実現するために、商品グループという仕組みがあります。 商品グループは、商品ごとに優先度を付けて複数の商品をまとめる仕組みで、購入可能な条件を満たし、かつもっとも優先度の高い商品が陳列されます。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

使い方は2ステップです。

  1. マスターを作成する
  2. 商品を購入する

マスターを作成する

マスターは3種類です。

商品マスター

商品の値段と報酬を決めます。 お金とゲーム内通貨の交換のほか、ゲーム内通貨でガチャを回したりスタミナを増やしたりなど様々な定義ができます。

商品グループマスター

商品マスターをグループ化します。用途としては例えば初回割引を実現する場合に割引価格商品⇒通常価格商品の順に登録する、ステップアップガチャを順番に登録するなどがあります。

商品マスターは商品グループマスターでグループ化しなくても売ることが可能です。

陳列棚マスター

作成した商品マスターと商品グループマスターを登録します。 お店に商品を並べるイメージで、商品マスターと商品グループマスターは陳列棚マスターに登録しないと売ることができません。

商品を購入する

交換を購入する例(Unity)

yield return gs2.Showcase.Buy(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.Name); // string 商品名
            Debug.Log(r.Result.Item.Metadata); // string 商品のメタデータ
            Debug.Log(r.Result.Item.ConsumeActions); // list[ConsumeAction] 消費アクションリスト
            Debug.Log(r.Result.Item.AcquireActions); // list[AcquireAction] 入手アクションリスト
            Debug.Log(r.Result.StampSheet); // string 購入処理の実行に使用するスタンプシート
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    showcaseName,   //  商品名
    displayItemId,   //  陳列商品ID
    config   //  設定値(オプション値)
);

ここで注意する点は'buy' 自体を実行するだけでは商品の購入は行われないことです。 'buy'の返り値であるスタンプシートを処理することで処理が行われます。 スタンプシートについては はじめかた⇒スタンプシートのページをご確認ください。 また一つの商品に複数の報酬を設定する場合はGS2-JobQueueと連携する必要があります。

GS2-Stamina

サービス概要

現実時間経過によって回復するスタミナ値を実現します。

スタミナには回復間隔と回復量を設定できます。 スタミナには2段階の最大値を設定できます。 1つ目は時間経過による自然回復の最大値。2つ目はUIの都合による最大値です。

GS2では、レベルアップ時にスタミナを全回復するときに公平性を期するため、自然回復の最大値を超えて回復できるようにしています。 一方で、これを無制限に許可してしまうと、UIに破綻をきたしてしまう可能性があります。 そのため、二段階目の最大値を設けており、仮にこちらを超えるようなことが会っても GS2-Distributor を使用していればプレゼントボックスにスタミナ回復リソースを届けられるようになっています。

この仕組みを応用すると、街づくりゲームの採集機能も実装できます。 スタミナモデルに建築物を設定し、スタミナ値を建築物の生産量をとして表現します。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

同一スタミナに対する操作は1秒間に3回までにおさえてください。 異なるユーザや、同一ユーザでも異なるスタミナモデルに対する処理であればこの制限はありません。

基本的な使い方

使い方は2ステップです。

  1. マスターを作成する
  2. スタミナを消費する

マスターを作成する

マスターは4種類あります。

スタミナモデルマスター

スタミナの最大値、回復間隔、回復量を定義します。

ただし、多くのスタミナ制ゲームではプレイヤーのランクによって最大値が増えるものが多いでしょう。 これを実現するにはスタミナモデルマスター設定ページの下部にあるGS2-Experience 連携を使用します。 使用方法は次項で説明していきます。

スタミナの最大値テーブルマスター

プレイヤーのランクによってスタミナの最大値を変化させる設定です。 プレイヤーのランクはGS2-Experienceで実現します。 事前に経験値の種類マスター(経験値ごとにどのランクになるかを定義するもの)を作成します。 こちらはGS2-Experienceのページをご確認ください。

経験値の種類マスターを作成したらスタミナの最大値テーブルマスターに登録し、 今度はランクごとのスタミナの最大値を定義します。 スタミナの最大値テーブルマスターは作成後、スタミナモデルマスターに登録することを忘れないでください。

ランクアップ時にスタミナを回復させる

多くのスタミナ制ゲームではランクアップ時にスタミナが最大値分回復するものが多いです。 これを実現したい場合はGS2-Scriptを使用します。 スタミナの最大値分スタミナを回復するGS2-Scriptを作成し、 GS2-Experienceのネームスペース設定のランク変化したときに実行するスクリプトに登録します。

こちらはGS2-Scriptのページをご確認ください。

スタミナ回復間隔テーブルマスター&スタミナ回復量テーブルマスター

スタミナの最大値テーブルマスターに加え、ランクによって回復間隔と回復量も変化させるマスターです。 ただし多くのスタミナ制ゲームでは、スタミナの回復効率まで変化するものはあまりありません。

使い道としてゲーム内の畑や鉱山といった時間経過によって資源が得られるシステムが考えられます。 スタミナを資源の量と見立てて、施設のレベルに応じて入手効率を変化させることができます。

スタミナを消費する

スタミナの消費方法は2つあります。

スタンプシートでの消費

例えば、マネージメントコンソールでGS2-Quest⇒クエストグループモデルマスター⇒クエストモデルマスターを開いてみてください。 クエストの参加料として「Stamina:スタミナを消費」が選択できます。このように他のサービスと連携して、何かをするためにスタミナを消費する仕組みが実装できます。

クライアントもしくはサーバーからAPIを呼び出して消費

クライアントからスタミナを消費する例(Unity)


yield return gs2.Stamina.Consume(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.Item.StaminaName); // string スタミナモデルの名前
            Debug.Log(r.Result.Item.Value); // integer 最終更新時におけるスタミナ値
            Debug.Log(r.Result.Item.MaxValue); // integer スタミナの最大値
            Debug.Log(r.Result.Item.RecoverIntervalMinutes); // integer スタミナの回復間隔(分)
            Debug.Log(r.Result.Item.RecoverValue); // integer スタミナの回復量
            Debug.Log(r.Result.Item.NextRecoverAt); // long 次回スタミナが回復する時間
            Debug.Log(r.Result.StaminaModel.Name); // string スタミナの種類名
            Debug.Log(r.Result.StaminaModel.Metadata); // string スタミナの種類のメタデータ
            Debug.Log(r.Result.StaminaModel.RecoverIntervalMinutes); // integer スタミナを回復する速度(分)
            Debug.Log(r.Result.StaminaModel.RecoverValue); // integer 時間経過後に回復する量
            Debug.Log(r.Result.StaminaModel.InitialCapacity); // integer スタミナの最大値の初期値
            Debug.Log(r.Result.StaminaModel.IsOverflow); // boolean 最大値を超えて回復するか
            Debug.Log(r.Result.StaminaModel.MaxCapacity); // integer 溢れた状況での最大値
            Debug.Log(r.Result.StaminaModel.MaxStaminaTable.Name); // string 最大スタミナ値テーブル名
            Debug.Log(r.Result.StaminaModel.MaxStaminaTable.Metadata); // string 最大スタミナ値テーブルのメタデータ
            Debug.Log(r.Result.StaminaModel.MaxStaminaTable.ExperienceModelId); // string 経験値の種類マスター のGRN
            Debug.Log(r.Result.StaminaModel.MaxStaminaTable.Values); // list[integer] ランク毎のスタミナの最大値テーブル
            Debug.Log(r.Result.StaminaModel.RecoverIntervalTable.Name); // string スタミナ回復間隔テーブル名
            Debug.Log(r.Result.StaminaModel.RecoverIntervalTable.Metadata); // string スタミナ回復間隔テーブルのメタデータ
            Debug.Log(r.Result.StaminaModel.RecoverIntervalTable.ExperienceModelId); // string 経験値の種類マスター のGRN
            Debug.Log(r.Result.StaminaModel.RecoverIntervalTable.Values); // list[integer] ランク毎のスタミナ回復間隔テーブル
            Debug.Log(r.Result.StaminaModel.RecoverValueTable.Name); // string スタミナ回復量テーブル名
            Debug.Log(r.Result.StaminaModel.RecoverValueTable.Metadata); // string スタミナ回復量テーブルのメタデータ
            Debug.Log(r.Result.StaminaModel.RecoverValueTable.ExperienceModelId); // string 経験値の種類マスター のGRN
            Debug.Log(r.Result.StaminaModel.RecoverValueTable.Values); // list[integer] ランク毎のスタミナ回復量テーブル
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    staminaName,   //  スタミナの種類名
    consumeValue,   //  消費するスタミナ量
);

サーバーからスタミナを消費する例(Unity)


from gs2_stamina_client.request import ConsumeStaminaByUserIdRequest
from gs2_stamina_client.result import ConsumeStaminaByUserIdResult

result = client.consume_stamina_by_user_id(
    ConsumeStaminaByUserIdRequest()\
        .with_namespace_name('namespace-0002')\
        .with_stamina_name('stamina-0002')\
        .with_user_id('user-0001')\
        .with_consume_value(5)
)

前項と違い、ゲーム独自のシステムでスタミナを消費したい場合はこちらを使用します。

GS2-Version

サービス概要

ゲームのバージョンチェックを実現します。 バージョンチェックを通過すると、新しいプロジェクトトークンを取得できます。 つまり、ゲームに組み込むクレデンシャルはバージョンチェックを行うのに十分な権限のみ付与し、 バージョンチェックを通過することでゲームを動作させるのに十分な権限のプロジェクトトークンを取得できるようにすることで、 バージョンチェックを通らなければゲームが遊べない状態を作り出します。

ネームスペースには最大10個のバージョンモデルを宣言でき、すべてのバージョンが要求バージョン以上のときにのみバージョンチェックを通過とみなします。

利用料金

一般的な利用料金

APIリクエスト 1回あたり 0.02円

サービス固有の利用料金

サービス固有の利用料金はありません

制限・制約

利用いただくにあたって注意いただく制限・制約はありません

基本的な使い方

使い方は3ステップです。

  1. マスターを作成する
  2. バージョンの認証を実行できるセキュリティポリシーの作成
  3. バージョンの認証をする

マスターを作成する

マネージメントコンソールから作成します。 バージョンマスターに設定するバージョンは、クライアントに最新またはそれに類するバージョンでないことを知らせるためのバージョンになります。 よってマスターには最新のバージョンは登録しません。

クライアントのバージョンが、マスターで登録したバージョンに一致しなかったということがゲームをプレイするうえで問題ないバージョンであることを証明します。

バージョンマスターはネームスペース当たり10個まで登録することができ、最大10のバージョンの検問を通過出来た場合にゲームがプレイできる、ということができます。

バージョン認証のみを実行できるセキュリティポリシーの作成

基本的な使い方として以下の手順があります。

  1. ゲームにはバージョンチェックを行うのに十分な権限を持つクレデンシャルのみを付与しておく
  2. ゲームを起動したらまず1のクレデンシャルを使ってバージョンチェックを行う 3a. バージョンチェックに通ったらゲームを動作させるのに十分なプロジェクトトークンを取得させる 3b. バージョンチェックに通らなければ、アプリストアなどに誘導してバージョンアップさせる

ここでバージョンチェックを行うのに十分な権限を持つクレデンシャルを作成する必要があります。 これについてはGS2-Identifierのページをご確認ください。

バージョンの認証をする

クライアントのバージョン情報を準備する例(Unity)

    List<EzTargetVersion> targetVersions = new List<EzTargetVersion>();
    EzTargetVersion targetVersion = new EzTargetVersion();
    targetVersion.VersionName = "test";
    EzVersion version = new EzVersion();
    version.Major = 1; //実際のクライアントのバージョンを入力
    version.Minor = 2; //実際のクライアントのバージョンを入力
    version.Micro = 3; //実際のクライアントのバージョンを入力
    targetVersion.Version = version;
    targetVersions.Add(targetVersion);

バージョンチェックを行う例(Unity)

yield return gs2.Version.CheckVersion(
    r => {
        if (r.Error != null)
        {
            // エラーが発生した場合に到達
            // r.Error は発生した例外オブジェクトが格納されている
        }
        else
        {
            Debug.Log(r.Result.ProjectToken); // string プロジェクトトークン
            Debug.Log(r.Result.Warnings); // list[Status] バージョンの検証結果のリスト
            Debug.Log(r.Result.Errors); // list[Status] バージョンの検証結果のリスト
        }
    },
    gameSession,    // GameSession ログイン状態を表すセッションオブジェクト
    namespaceName,   //  ネームスペース名
    targetVersions   //  加算するリソース(オプション値)
);

バージョンの認証するためにまず、クライアントのバージョン情報を準備します。(サンプルコード) その後、バージョン情報を引数にバージョンの認証のAPIを実行します。(サンプルコード) その返り値である、'Warnings' と'Errors' に通過できなかったバージョン情報が入っています。 'Warnings' と'Errors'はリストですので、それぞれのサイズが0であればバージョンに問題なし=ゲームを開始する、どちらかのサイズが1以上であればバージョンに問題あり=バージョンアップを促す、という処理が書けます。

スタンプシート

スタンプシートとは

スタンプシートの概念

GS2 では各サービス間を連携させる仕組みとして、 スタンプシート というシステムを使用します。 スタンプシート は 企業における稟議書のようなもので、 結果 を得るために 許可 を得ていく処理を表現し、 最後に 結果 を処理するパートは 許可 を得たことで得られる署名が揃っていること だけを見て処理を実行します。

GS2 において 結果は報酬 許可は対価 として処理されます。 つまり、すべてのサービス間の連携は 対価報酬 で表現され、例えばクエストでは スタミナや回数制限のカウンター上昇を対価 として 経験値やクリアフラグを報酬として得る となります。 スタンプシートの 対価 を支払う処理を スタンプタスク とよび、サービスに スタンプタスク を持っていき 対価 を支払うとスタンプシートにスタンプを押してもらえます。 最後に 報酬 を付与するサービスに スタンプシート を持っていくと、 スタンプタスク にすべてスタンプが押されていることを確認して 報酬 が付与されます。

スタンプシートの変数

スタンプシートスタンプタスク は処理の実態としてGS2のリクエストを発行します。 スタンプタスク には対価を払う処理ですので、プレイヤーのリソースを減らす処理ののリクエストが設定でき、 スタンプシート はその逆です。 それぞれ、どの ユーザのリソースを操作するか という情報をリクエストに含める必要がありますが、ゲーム内ストアやクエストのマスターデータに直接ユーザIDを指定するのは不可能です。 そこで、 スタンプシート のリクエストには変数が適用できます。

Config

報酬の内容に #{userId} というプレースホルダーを設定すると、 その部分はスタンプシートを発行する際にスタンプシートの発行をおこなったプレイヤーのユーザIDに置換されます。

その他、スタンプシートの発行リクエストには Config というパラメータが渡せるようになっています。 Config はキーバリュー形式となっており、ここで渡したパラメータは #{Config で指定したキー値} のプレースホルダを置換するのに使用できます。

タスクの実行結果

報酬の内容に ${Gs2Money:WithdrawByUserId.price} というプレースホルダーを設定すると、 その部分は スタンプタスク の実行結果を変数として利用できます。 例に示したケースでは 実行したタスクのうち Gs2Money:WithdrawByUserId の実行結果を参照し、戻り値の price を値として使用します。 ネストした要素を参照する場合は ${Gs2Money:WithdrawByUserId.item.paid} のようにドットでつないで参照できます。

同一のアクションが スタンプタスク として複数登録されている場合に採用される値は不定です。

スタンプシートの一覧

Gs2Dictionary:AddEntriesByUserId

スタンプシートでエントリーを追加

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}",
  "entryModelNames": "[string[]]エントリー名のリスト"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID
entryModelNames string[] [] エントリー名のリスト

Gs2Enhance:DirectEnhanceByUserId

スタンプシートで強化を実行

{
  "namespaceName": "[string]ネームスペース名",
  "rateName": "[string]強化レート名",
  "userId": "#{userId}",
  "targetItemSetId": "[string]有効期限ごとのアイテム所持数量GRN",
  "materials": "[Material[]]強化素材リスト",
  "config": "[Config[]]設定値"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
rateName string ~ 128文字 強化レート名
userId string ~ 128文字 ユーザーID
targetItemSetId string ~ 1024文字 有効期限ごとのアイテム所持数量GRN
materials Material[] 強化素材リスト
config Config[] [] 設定値

Gs2Enhance:CreateProgressByUserId

スタンプシートで強化を開始

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}",
  "rateName": "[string]レートモデル名",
  "targetItemSetId": "[string]有効期限ごとのアイテム所持数量GRN",
  "materials": "[Material[]]強化素材リスト",
  "force": "[bool]すでに開始している強化がある場合にそれを破棄して開始するか"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID
rateName string ~ 128文字 レートモデル名
targetItemSetId string ~ 1024文字 有効期限ごとのアイテム所持数量GRN
materials Material[] 強化素材リスト
force bool false すでに開始している強化がある場合にそれを破棄して開始するか

Gs2Exchange:ExchangeByUserId

スタンプシートで交換を実行

{
  "namespaceName": "[string]ネームスペース名",
  "rateName": "[string]交換レートの種類名",
  "userId": "#{userId}",
  "count": "[int]交換するロット数",
  "config": "[Config[]]設定値"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
rateName string ~ 128文字 交換レートの種類名
userId string ~ 128文字 ユーザーID
count int 1 ~ 9223372036854775807 交換するロット数
config Config[] [] 設定値

Gs2Exchange:CreateAwaitByUserId

スタンプシートで交換待機 を作成

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}",
  "rateName": "[string]交換レート名",
  "count": "[int]交換数"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID
rateName string ~ 128文字 交換レート名
count int 1 1 ~ 10000 交換数

Gs2Experience:AddExperienceByUserId

経験値を加算

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}",
  "experienceName": "[string]経験値の種類の名前",
  "propertyId": "[string]プロパティID",
  "experienceValue": "[long]獲得経験値"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID
experienceName string ~ 128文字 経験値の種類の名前
propertyId string ~ 1024文字 プロパティID
experienceValue long 0 ~ 9223372036854775807 獲得経験値

Gs2Experience:AddRankCapByUserId

ランクキャップを加算

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}",
  "experienceName": "[string]経験値の種類の名前",
  "propertyId": "[string]プロパティID",
  "rankCapValue": "[long]現在のランクキャップ"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID
experienceName string ~ 128文字 経験値の種類の名前
propertyId string ~ 1024文字 プロパティID
rankCapValue long ~ 9223372036854775807 現在のランクキャップ

Gs2Experience:SetRankCapByUserId

ランクキャップを更新

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}",
  "experienceName": "[string]経験値の種類の名前",
  "propertyId": "[string]プロパティID",
  "rankCapValue": "[long]現在のランクキャップ"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID
experienceName string ~ 128文字 経験値の種類の名前
propertyId string ~ 1024文字 プロパティID
rankCapValue long ~ 9223372036854775807 現在のランクキャップ

Gs2Formation:AddMoldCapacityByUserId

スタンプシートでキャパシティサイズを加算

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}",
  "moldName": "[string]フォームの保存領域の名前",
  "capacity": "[int]現在のキャパシティ"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID
moldName string ~ 128文字 フォームの保存領域の名前
capacity int ~ 9223372036854775807 現在のキャパシティ

Gs2Formation:SetMoldCapacityByUserId

スタンプシートでキャパシティサイズを設定

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}",
  "moldName": "[string]フォームの保存領域の名前",
  "capacity": "[int]現在のキャパシティ"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID
moldName string ~ 128文字 フォームの保存領域の名前
capacity int ~ 9223372036854775807 現在のキャパシティ

Gs2Formation:AcquireActionsToFormProperties

スタンプシートでアイテムをインベントリに追加

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}",
  "moldName": "[string]フォームの保存領域の名前",
  "index": "[int]保存領域のインデックス",
  "acquireAction": "[AcquireAction]フォームのプロパティに適用する入手アクション",
  "queueNamespaceId": "[string]スタンプシートの実行に使用する GS2-JobQueue のネームスペース",
  "keyId": "[string]スタンプシートの発行に使用する GS2-Key のネームスペース",
  "config": "[AcquireActionConfig[]]入手アクションに適用するコンフィグ"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID
moldName string ~ 128文字 フォームの保存領域の名前
index int ~ 9223372036854775807 保存領域のインデックス
acquireAction AcquireAction フォームのプロパティに適用する入手アクション
queueNamespaceId string ~ 1024文字 スタンプシートの実行に使用する GS2-JobQueue のネームスペース
keyId string ~ 1024文字 スタンプシートの発行に使用する GS2-Key のネームスペース
config AcquireActionConfig[] [] 入手アクションに適用するコンフィグ

Gs2Inventory:AddCapacityByUserId

スタンプシートでキャパシティサイズを加算

{
  "namespaceName": "[string]ネームスペース名",
  "inventoryName": "[string]インベントリモデル名",
  "userId": "#{userId}",
  "addCapacityValue": "[int]加算するキャパシティサイズ"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
inventoryName string ~ 128文字 インベントリモデル名
userId string ~ 128文字 ユーザーID
addCapacityValue int 1 ~ 9223372036854775807 加算するキャパシティサイズ

Gs2Inventory:SetCapacityByUserId

スタンプシートでキャパシティサイズを設定

{
  "namespaceName": "[string]ネームスペース名",
  "inventoryName": "[string]インベントリモデル名",
  "userId": "#{userId}",
  "newCapacityValue": "[int]現在のインベントリの最大キャパシティ"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
inventoryName string ~ 128文字 インベントリモデル名
userId string ~ 128文字 ユーザーID
newCapacityValue int 1 ~ 9223372036854775807 現在のインベントリの最大キャパシティ

Gs2Inventory:AcquireItemSetByUserId

スタンプシートでアイテムをインベントリに追加

{
  "namespaceName": "[string]ネームスペース名",
  "inventoryName": "[string]インベントリの名前",
  "itemName": "[string]アイテムマスターの名前",
  "userId": "#{userId}",
  "acquireCount": "[long]入手する量",
  "expiresAt": "[long]有効期限",
  "createNewItemSet": "[bool]既存の ItemSet に空きがあったとしても、新しい ItemSet を作成するか",
  "itemSetName": "[string]アイテムセットを識別する名前"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
inventoryName string ~ 128文字 インベントリの名前
itemName string ~ 128文字 アイテムマスターの名前
userId string ~ 128文字 ユーザーID
acquireCount long 1 ~ 9223372036854775807 入手する量
expiresAt long 0 有効期限
createNewItemSet bool false 既存の ItemSet に空きがあったとしても、新しい ItemSet を作成するか
itemSetName string UUID ~ 36文字 アイテムセットを識別する名前

Gs2Inventory:AddReferenceOfByUserId

スタンプシートでアイテムに参照元を追加

{
  "namespaceName": "[string]ネームスペース名",
  "inventoryName": "[string]インベントリの名前",
  "userId": "#{userId}",
  "itemName": "[string]アイテムマスターの名前",
  "itemSetName": "[string]アイテムセットを識別する名前",
  "referenceOf": "[string]この所持品の参照元"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
inventoryName string ~ 128文字 インベントリの名前
userId string ~ 128文字 ユーザーID
itemName string ~ 128文字 アイテムマスターの名前
itemSetName string UUID ~ 36文字 アイテムセットを識別する名前
referenceOf string ~ 1024文字 この所持品の参照元

Gs2Inventory:DeleteReferenceOfByUserId

スタンプシートでアイテムの参照元を削除

{
  "namespaceName": "[string]ネームスペース名",
  "inventoryName": "[string]インベントリの名前",
  "userId": "#{userId}",
  "itemName": "[string]アイテムマスターの名前",
  "itemSetName": "[string]アイテムセットを識別する名前",
  "referenceOf": "[string]この所持品の参照元"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
inventoryName string ~ 128文字 インベントリの名前
userId string ~ 128文字 ユーザーID
itemName string ~ 128文字 アイテムマスターの名前
itemSetName string UUID ~ 36文字 アイテムセットを識別する名前
referenceOf string ~ 1024文字 この所持品の参照元

Gs2JobQueue:PushByUserId

スタンプシートでジョブを登録

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}",
  "jobs": "[JobEntry[]]追加するジョブの一覧"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID
jobs JobEntry[] 追加するジョブの一覧

Gs2Limit:DeleteCounterByUserId

スタンプシートでカウンターを削除

{
  "namespaceName": "[string]ネームスペース名",
  "limitName": "[string]回数制限の種類の名前",
  "userId": "#{userId}",
  "counterName": "[string]カウンターの名前"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
limitName string ~ 128文字 回数制限の種類の名前
userId string ~ 128文字 ユーザーID
counterName string ~ 128文字 カウンターの名前

Gs2Lottery:DrawByUserId

スタンプシートを使用して抽選処理を実行

{
  "namespaceName": "[string]ネームスペース名",
  "lotteryName": "[string]抽選モデルの種類名",
  "userId": "#{userId}",
  "count": "[int]抽選回数",
  "config": "[Config[]]スタンプシートのプレースホルダの適用する設定値"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
lotteryName string ~ 128文字 抽選モデルの種類名
userId string ~ 128文字 ユーザーID
count int ~ 1000 抽選回数
config Config[] [] スタンプシートのプレースホルダの適用する設定値

Gs2Mission:IncreaseCounterByUserId

カウンター加算

{
  "namespaceName": "[string]ネームスペース名",
  "counterName": "[string]カウンター名",
  "userId": "#{userId}",
  "value": "[long]加算する値"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
counterName string ~ 128文字 カウンター名
userId string ~ 128文字 ユーザーID
value long 1 ~ 9223372036854775807 加算する値

Gs2Money:DepositByUserId

スタンプシートを使用してウォレットに残高を加算します

{
  "namespaceName": "[string]ネームスペースの名前",
  "userId": "#{userId}",
  "slot": "[int]スロット番号",
  "price": "[float]購入価格",
  "count": "[int]付与する課金通貨の数量"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペースの名前
userId string ~ 128文字 ユーザーID
slot int ~ 100000000 スロット番号
price float ~ 100000.0 購入価格
count int 1 ~ 9223372036854775807 付与する課金通貨の数量

Gs2Quest:CreateProgressByUserId

スタンプシートでクエストを開始

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}",
  "questModelId": "[string]進行中のクエスト",
  "force": "[bool]すでに開始しているクエストがある場合にそれを破棄して開始するか",
  "config": "[Config[]]スタンプシートの変数に適用する設定値"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID
questModelId string ~ 1024文字 進行中のクエスト
force bool false すでに開始しているクエストがある場合にそれを破棄して開始するか
config Config[] [] スタンプシートの変数に適用する設定値

Gs2Stamina:RecoverStaminaByUserId

スタンプシートを使用してスタミナを回復

{
  "namespaceName": "[string]ネームスペース名",
  "staminaName": "[string]スタミナモデルの名前",
  "userId": "#{userId}",
  "recoverValue": "[int]スタミナの回復量"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
staminaName string ~ 128文字 スタミナモデルの名前
userId string ~ 128文字 ユーザーID
recoverValue int 1 ~ 9223372036854775807 スタミナの回復量

Gs2Stamina:RaiseMaxValueByUserId

スタンプシートでスタミナの最大値を加算

{
  "namespaceName": "[string]ネームスペース名",
  "staminaName": "[string]スタミナモデルの名前",
  "userId": "#{userId}",
  "raiseValue": "[int]上昇する最大スタミナ量"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
staminaName string ~ 128文字 スタミナモデルの名前
userId string ~ 128文字 ユーザーID
raiseValue int ~ 9223372036854775807 上昇する最大スタミナ量

Gs2Stamina:SetMaxValueByUserId

スタンプシートでスタミナの最大値を更新

{
  "namespaceName": "[string]ネームスペース名",
  "staminaName": "[string]スタミナモデルの名前",
  "userId": "#{userId}",
  "maxValue": "[int]スタミナの最大値"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
staminaName string ~ 128文字 スタミナモデルの名前
userId string ~ 128文字 ユーザーID
maxValue int 1 ~ 9223372036854775807 スタミナの最大値

Gs2Stamina:SetRecoverIntervalByUserId

スタンプシートでスタミナの最大値を更新

{
  "namespaceName": "[string]ネームスペース名",
  "staminaName": "[string]スタミナモデルの名前",
  "userId": "#{userId}",
  "recoverIntervalMinutes": "[int]スタミナの回復間隔(分)"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
staminaName string ~ 128文字 スタミナモデルの名前
userId string ~ 128文字 ユーザーID
recoverIntervalMinutes int 1 ~ 9223372036854775807 スタミナの回復間隔(分)

Gs2Stamina:SetRecoverValueByUserId

スタンプシートでスタミナの最大値を更新

{
  "namespaceName": "[string]ネームスペース名",
  "staminaName": "[string]スタミナモデルの名前",
  "userId": "#{userId}",
  "recoverValue": "[int]スタミナの回復量"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
staminaName string ~ 128文字 スタミナモデルの名前
userId string ~ 128文字 ユーザーID
recoverValue int 1 ~ 9223372036854775807 スタミナの回復量

スタンプタスクの一覧

Gs2Enhance:DeleteProgressByUserId

スタンプタスクで 強化実行 を削除

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID

Gs2Exchange:DeleteAwaitByUserId

スタンプタスクで 交換待機 を削除

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}",
  "rateName": "[string]交換レート名",
  "awaitName": "[string]交換待機の名前"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID
rateName string ~ 128文字 交換レート名
awaitName string UUID ~ 36文字 交換待機の名前

Gs2Inbox:OpenMessageByUserId

メッセージを作成

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}",
  "messageName": "[string]メッセージID"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID
messageName string UUID ~ 36文字 メッセージID

Gs2Inventory:ConsumeItemSetByUserId

スタンプシートでインベントリのアイテムを消費

{
  "namespaceName": "[string]ネームスペース名",
  "inventoryName": "[string]インベントリの名前",
  "userId": "#{userId}",
  "itemName": "[string]アイテムマスターの名前",
  "consumeCount": "[long]消費する量",
  "itemSetName": "[string]アイテムセットを識別する名前"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
inventoryName string ~ 128文字 インベントリの名前
userId string ~ 128文字 ユーザーID
itemName string ~ 128文字 アイテムマスターの名前
consumeCount long 1 ~ 9223372036854775807 消費する量
itemSetName string UUID ~ 36文字 アイテムセットを識別する名前

Gs2Inventory:VerifyReferenceOfByUserId

スタンプシートでインベントリのアイテムを検証

{
  "namespaceName": "[string]ネームスペース名",
  "inventoryName": "[string]インベントリの名前",
  "userId": "#{userId}",
  "itemName": "[string]アイテムマスターの名前",
  "itemSetName": "[string]アイテムセットを識別する名前",
  "referenceOf": "[string]この所持品の参照元",
  "verifyType": "[string]検証の種類"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
inventoryName string ~ 128文字 インベントリの名前
userId string ~ 128文字 ユーザーID
itemName string ~ 128文字 アイテムマスターの名前
itemSetName string UUID ~ 36文字 アイテムセットを識別する名前
referenceOf string ~ 1024文字 この所持品の参照元
verifyType string ~ 128文字 検証の種類

Gs2Limit:CountUpByUserId

スタンプシートでカウントアップ

{
  "namespaceName": "[string]ネームスペース名",
  "limitName": "[string]回数制限の種類の名前",
  "counterName": "[string]カウンターの名前",
  "userId": "#{userId}",
  "countUpValue": "[int]カウントアップする量",
  "maxValue": "[int]カウントアップを許容する最大値 を入力してください"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
limitName string ~ 128文字 回数制限の種類の名前
counterName string ~ 128文字 カウンターの名前
userId string ~ 128文字 ユーザーID
countUpValue int 1 1 ~ 9223372036854775807 カウントアップする量
maxValue int 1 ~ 9223372036854775807 カウントアップを許容する最大値 を入力してください

Gs2Mission:ReceiveByUserId

達成状況を作成

{
  "namespaceName": "[string]ネームスペース名",
  "missionGroupName": "[string]ミッショングループ名",
  "missionTaskName": "[string]タスク名",
  "userId": "#{userId}"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
missionGroupName string ~ 128文字 ミッショングループ名
missionTaskName string ~ 128文字 タスク名
userId string ~ 128文字 ユーザーID

Gs2Money:WithdrawByUserId

ウォレットから残高を消費します

{
  "namespaceName": "[string]ネームスペースの名前",
  "userId": "#{userId}",
  "slot": "[int]スロット番号",
  "count": "[int]消費する課金通貨の数量",
  "paidOnly": "[bool]有償課金通貨のみを対象とするか"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペースの名前
userId string ~ 128文字 ユーザーID
slot int ~ 100000000 スロット番号
count int 1 ~ 9223372036854775807 消費する課金通貨の数量
paidOnly bool false 有償課金通貨のみを対象とするか

Gs2Money:RecordReceipt

スタンプシートを使用してレシートを記録

{
  "namespaceName": "[string]ネームスペースの名前",
  "userId": "#{userId}",
  "contentsId": "[string]ストアプラットフォームで販売されているコンテンツID",
  "receipt": "[string]レシート"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペースの名前
userId string ~ 128文字 ユーザーID
contentsId string ~ 1024文字 ストアプラットフォームで販売されているコンテンツID
receipt string ~ 1048576文字 レシート

Gs2Quest:DeleteProgressByUserId

スタンプタスクで クエスト挑戦 を削除

{
  "namespaceName": "[string]ネームスペース名",
  "userId": "#{userId}"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
userId string ~ 128文字 ユーザーID

Gs2Stamina:ConsumeStaminaByUserId

スタンプタスクを使用してスタミナを消費

{
  "namespaceName": "[string]ネームスペース名",
  "staminaName": "[string]スタミナモデルの名前",
  "userId": "#{userId}",
  "consumeValue": "[int]消費するスタミナ量"
}
必須 デフォルト 値の制限 説明
namespaceName string ~ 32文字 ネームスペース名
staminaName string ~ 128文字 スタミナモデルの名前
userId string ~ 128文字 ユーザーID
consumeValue int 1 ~ 9223372036854775807 消費するスタミナ量

用語集

一般

GRN のフォーマット

grn:gs2:{リージョン}:{オーナーID}:{サービス名}:{モデル名}:{代替キー}:{モデル名}:{代替キー}...

リージョンの種類

ap-northeast-1 = 日本

ポリシードキュメントのフォーマット
Actions に呼び出せるアクションを羅列し、Resources に操作出来る対象リソースを羅列する
Actions / Resources には末尾にのみワイルドカードを使用出来る

{
    'Version': '2016-04-01',
    'Statements': [
        {
            'Effect': 'Allow',
            'Actions': [
                'Gs2Account:Create*',
            ],
            'Resources': ['*'],
        },
    ]
}
用語 意味
GRN Gs2 Resource Name
GS2 が扱うすべての情報に付与される一意なリソース名
サービス名 GS2 のマイクロサービスの種類
リージョン GS2 が動作しているデータセンターの場所。
アカウントID GS2 のアカウントを一意に識別するためのID
プロジェクトID ゲームを一意に識別するためのID。アカウントIDに複数紐づけて管理
オーナーID {アカウントID}${プロジェクトID}
GS2内のデータは基本的にこの情報に紐づけて保存される
ユーザID ゲームプレイヤーを識別するID
アクセストークン GS2-Auth によってゲームプレイヤーの認証がおこなわれた証明として払い出されるトークン
各マイクロサービスが利用者のユーザIDを特定する為に使用される

有効期限が設定されており、発行から10時間で再取得が必要となる。
プロジェクトトークン クレデンシャル を使用して取得する一時的な認証トークン。
Open ID Connect ベースで実装されており、Open ID Connect 的に言うと IDトークン。

有効期限が設定されており、発行から10時間で再取得が必要となる。
セキュリティポリシー GS2-Identifier のユーザに紐付けて管理される権限
クライアントIDを使用してどのAPI操作を行えるかを定義する
ポリシードキュメント セキュリティポリシー の権限設定を定義した JSON ドキュメント
モデル GS2 内のエンティティの型
エンティティ モデルを実体化したもの
代替キー エンティティのGRN以外のエンティティ固有の値を格納したフィールド名
GS2-Account の Game: gameName, Account: userId, TakeOver: type, userIdentifier
アクション API の種類を表す識別子 Gs2Inbox:CreateInbox のように定義され、前半部はサービスを表し、後半部はアクションの種類を表す。
プロパティID ゲーム内のキャラクターやアイテムを一意に識別するためのID
リソースGRN ゲームプレイヤーの所持物のGRNの総称
GS2-Inventory の所持物や、GS2-Experience の経験値情報、GS2-Stamina のスタミナ値など
リクエストID GS2 に対するAPIリクエスト毎に割り当てられるID
そのAPIより派生した GS2-Script 内のAPIアクセスなどは同じリクエストIDが共有される

リクエストID によって一連の処理の流れを追跡することが可能となり、
トランザクション処理においては、同一処理系によるデッドロックが発生することを避けることができる
コンテキスト GS2 のリクエストIDに割り当てられたスタック領域の名前
あるいは同一リクエストIDの処理系におけるスタック領域の状態。
スタック領域 リクエストIDが同一の処理系において処理がチェインする毎に積み重ねるメモリ空間

GS2-Account

用語 意味
アカウント認証情報・署名 GS2-Account によって認証が成功したときに発行される情報。署名をあわせて利用することで改ざん検出が可能
引き継ぎ設定 GS2-Account が発行したユーザIDとパスワードを復元するための設定。引き継ぎを実行するために必要となる任意の値を設定可能なユーザID・パスワードを保持する

GS2-Identifier

用語 意味
クライアントID API の利用者を識別する為のID
GS2-Identifier のユーザに紐付けて管理される
クライアントシークレット クライアントID が正規の利用者によって使用されていることを識別するためのキー
クレデンシャル クライアントID と クライアントシークレット の組み合わせ

GS2-Money

用語 意味
課金通貨 資金決済法の前払式支払手段(自家型)に該当するゲーム内通貨

GS2-Matchmaking

用語 意味
ギャザリング マッチメイキングによって作成されたプレイヤーの集合
ロール マッチメイキング時の条件に使用するプレイヤーの役割(タンク・ヒーラーなど)

サービス間の依存関係

GS2-Account

依存するサービス 依存する理由 依存する条件
GS2-Key::Key 認証結果の署名発行 必ず
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存

GS2-Auth

依存するサービス 依存する理由 依存する条件
GS2-Key::Key GS2-Account の認証結果の署名検証 GS2-Account の認証結果を使って アクセストークンの発行 をしようとしたとき

GS2-Chat

依存するサービス 依存する理由 依存する条件
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存

GS2-Distributor

依存するサービス 依存する理由 依存する条件
GS2-Identifier::User 報酬付与を実行する際に実行権限を設定したユーザが必要 必ず
GS2-Inbox::Namespace 報酬が溢れたときに GS2-Inbox に届けるのに必要 GS2-Inventory/GS2-Stamina への報酬付与を実行した場合に依存
その他すべて スタンプシートの実行のため スタンプシートの対価や報酬に設定されたマイクロサービスに依存

GS2-Exchange

依存するサービス 依存する理由 依存する条件
GS2-JobQueue::Namespace 報酬が複数存在する場合に報酬の付与に使用 報酬を複数設定した場合に依存
GS2-Key::Key スタンプシートの署名発行 必ず
その他すべて スタンプシートの発行のため スタンプシートの対価や報酬に設定するマイクロサービスに依存

GS2-Experience

依存するサービス 依存する理由 依存する条件
GS2-Key::Key スタンプシートの実行 スタンプシートで報酬を付与する場合に依存
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存

GS2-Formation

依存するサービス 依存する理由 依存する条件
GS2-Key::Key スタンプシートの実行 スタンプシートで報酬を付与する場合に依存
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存

GS2-Friend

依存するサービス 依存する理由 依存する条件
GS2-Key::Key スタンプシートの実行 スタンプシートで報酬を付与する場合に依存
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存
GS2-Gateway::Namespace フレンドリクエスト通知 常時接続通信セッションを利用してプッシュ通知を受ける設定をした場合に依存

GS2-Gateway

依存するサービス 依存する理由 依存する条件
Firebase::FCM モバイルプッシュ通知を送信する プッシュ通知リクエストの際に対象ユーザがオフラインだった場合、モバイルプッシュに転送するオプションが有効な場合に依存

GS2-Identifier

依存するサービス 依存する理由 依存する条件

GS2-Inbox

依存するサービス 依存する理由 依存する条件
GS2-Key::Key スタンプシートの実行 スタンプシートでメッセージを送信する場合に依存
GS2-Key::Key スタンプシートの発行 メッセージに報酬を添付する場合に依存
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存
GS2-JobQueue::Namespace 報酬が複数存在する場合に報酬の付与に使用 メッセージに複数の報酬を設定した場合に依存
GS2-Gateway::Namespace 新着メッセージ通知 常時接続通信セッションを利用してプッシュ通知を受ける設定をした場合に依存

GS2-Inventory

依存するサービス 依存する理由 依存する条件
GS2-Key::Key スタンプシートの実行 スタンプシートでアイテムを付与する場合に依存
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存

GS2-JobQueue

依存するサービス 依存する理由 依存する条件
GS2-Gateway::Namespace ジョブが登録された通知 常時接続通信セッションを利用してプッシュ通知を受ける設定をした場合に依存

GS2-Key

依存するサービス 依存する理由 依存する条件

GS2-Limit

依存するサービス 依存する理由 依存する条件
GS2-Key::Key スタンプシートの実行 スタンプシートでカウンターを加算する場合に依存

GS2-Lock

依存するサービス 依存する理由 依存する条件

GS2-Lottery

依存するサービス 依存する理由 依存する条件
GS2-Key::Key スタンプシートの実行 スタンプシートで抽選する場合に依存
GS2-Key::Key スタンプシートの発行 抽選する場合に依存
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存
GS2-JobQueue::Namespace 報酬が複数存在する場合に報酬の付与に使用 報酬に複数の報酬を設定した場合に依存

GS2-Matchmaking

依存するサービス 依存する理由 依存する条件
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存
GS2-Gateway::Namespace マッチメイキング進行通知 常時接続通信セッションを利用してプッシュ通知を受ける設定をした場合に依存

GS2-Mission

依存するサービス 依存する理由 依存する条件
GS2-Key::Key スタンプシートの実行 スタンプシートでカウンターを操作する場合に依存
GS2-Key::Key スタンプシートの発行 達成報酬を受け取る場合に依存
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存
GS2-JobQueue::Namespace 報酬が複数存在する場合に報酬の付与に使用 報酬に複数の報酬を設定した場合に依存
GS2-Schedule::Event ミッション開催期間を設定 開催期間のあるタスクを設定した場合に依存

GS2-Money

依存するサービス 依存する理由 依存する条件
GS2-Key::Key スタンプシートの実行 スタンプシートで残高を加算する場合に依存
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存

GS2-Quest

依存するサービス 依存する理由 依存する条件
GS2-Key::Key スタンプシートの実行 スタンプシートでクリアフラグを操作する場合に依存
GS2-Key::Key スタンプシートの発行 クエスト開始・完了処理を実行する場合に依存
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存
GS2-JobQueue::Namespace 報酬が複数存在する場合に報酬の付与に使用 報酬に複数の報酬を設定した場合に依存
GS2-Schedule::Event クエスト公開期間を設定 公開期間のあるクエストを設定した場合に依存

GS2-Ranking

依存するサービス 依存する理由 依存する条件
GS2-Key::Key スタンプシートの実行 スタンプシートでスコアを登録する場合に依存
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存

GS2-Realtime

依存するサービス 依存する理由 依存する条件
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存

GS2-Schedule

依存するサービス 依存する理由 依存する条件
GS2-Key::Key スタンプシートの実行 相対期間イベントトリガーを実行する場合に依存

GS2-Script

依存するサービス 依存する理由 依存する条件
すべて スクリプト内から GS2-SDK を利用可能なため スクリプト内から GS2-SDK を利用した場合に依存

GS2-Showcase

依存するサービス 依存する理由 依存する条件
GS2-Key::Key スタンプシートの発行 商品購入処理を実行する場合に依存
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存
GS2-JobQueue::Namespace 報酬が複数存在する場合に報酬の付与に使用 報酬に複数の報酬を設定した場合に依存
GS2-Schedule::Event 商品の販売期間を設定 販売期間のある商品を設定した場合に依存

GS2-Stamina

依存するサービス 依存する理由 依存する条件
GS2-Key::Key スタンプシートの実行 スタンプシートでスタミナ値を操作する場合に依存
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存

GS2-Version

依存するサービス 依存する理由 依存する条件
GS2-Key::Key クライアントから受け取ったバージョン情報が妥当か署名検証をするのに使用 クライアントからバージョン情報を受け取り、署名検証を有効にした場合に依存
GS2-Script::Script スクリプトの実行 イベントにスクリプトを設定した場合に依存
GS2-JobQueue::Namespace 各種登録完了スクリプトを遅延実行 完了イベントにスクリプトを設定し、なおかつジョブキューを設定した場合に依存