GS2 Blog

Game Server Services(https://gs2.io/) の最新情報をお届けします

【新サービス】GS2-Gacha の公開と GS2-Showcase のエンハンスのお知らせ

みなさん、こんにちは。GS2の丹羽です。

GS2-Gacha を公開

本日は新しいサービス GS2-Gacha の公開をお知らせします。
GS2-Gacha は名前の通りガチャの実装をサポートするためのサービスです。

GS2-Gacha の特徴

抽選確率の管理

レアリティ毎の抽選確率を設定し、そのレアリティ内でリソース毎の抽選確率を設定出来ます。 これによって、レアリティ毎の排出確率を調整する手間が省け、運用がスムーズになります。
また、抽選確率は重みベースの確率設定が可能で、登録したりソースの抽選確率の合計が100%になるよう調整するような手間もありません。
これはたとえば、リソースAを1に、リソースBを4に設定すると、リソースAの排出率が20%。リソースBの排出率が80%として処理されることを意味します。

GS2に登録した抽選確率をクライアントに提供する機能も存在します。 これによって、実際の抽選確率とドキュメントの抽選確率に齟齬が発生するような運用上のミスを最小限に抑えることが可能です。
GS2-Gacha においては、ガチャと排出確率テーブルは別途管理されており、異なるガチャで排出確率テーブルを使い回すことが出来ます。
これによって、単発ガチャと10連ガチャで同じ排出確率テーブルを共有することが可能です。

10連ガチャでSR以上確定のような実装も可能

10連ガチャのような複数回抽選するガチャにおいて、抽選回数毎に異なる排出確率テーブルを設定出来ます。 これによって、10連ガチャでSR以上確定。のような設定が可能です。

GS2-Showcase との連携

GS2-Showcase と連携することで、ガチャの公開期間や抽選回数の制限を設けることが出来ます。

GS2-Showcase のアップデート

実装方法も非常に簡単です。その話をする前に GS2-Showcase のエンハンスの話をします。

商品の購入通貨に GS2-ConsumableItem を追加

これまで GS2-Showcase の対価には ストア決済 / GS2-Money / GS2-Gold が指定出来ました。今回のエンハンスによって GS2-ConsumableItem に対応しました。
GS2-ConsumableItem に対応したことで、ガチャチケットのような機能を実装出来るようになります。

購入対象商品に GS2-Gacha を追加

もう一つのエンハンスは、購入対象に GS2-Gacha が追加されたことです。
これによって、GS2-Showcase にガチャを陳列することが出来るようになり、ガチャの抽選処理まで GS2-Showcase が発行するスタンプシートで処理出来るようになりました。
この機能を使用する場合は、GS2-Gacha の採用にあたって新しく実装をする必要は無く、GS2-Showcase に GS2-Gacha の商品を陳列するだけで対応出来ます!

GS2-Showcase の実装方法については以下のエントリを参考にしてください。
gs2.hatenablog.com

GS2-Gacha の使い方

GS2-Gacha に登録した景品の排出確率を取得するサンプルは以下です。

レアリティ毎の排出確率を取得

    yield return gs2.Gacha.GetGachaProbability(
        result => {
            if(result.Error != null) throw result.Error;
            EzGachaProbabilityList probabilities = result.Result;
            foreach (var item : probabilities)
            {
                Debug.Log("レアリティ名: " + item.Name);
                Debug.Log("排出確率: " + item.Rate);        // 0.0f〜1.0f
            }
        },
        session,            // GS2 ログインセッション
        GachaPoolName,      // GS2-Gacha で作成したガチャプール名
        GachaName,          // GS2-Gacha で作成したガチャ名
        1                   // 何回目の抽選における排出確率を取得するか
    );

リソース毎の排出確率を取得

    yield return gs2.Gacha.GetGachaProbabilityDetail(
        result => {
            if(result.Error != null) throw result.Error;
            EzGachaProbabilityDetailList probabilities = result.Result;
            foreach (var item : probabilities)
            {
                Debug.Log("レアリティ名: " + item.RarityName);
                Debug.Log("リソースID: " + item.ResourceId);
                Debug.Log("排出確率: " + item.Rate);        // 0.0f〜1.0f
            }
        },
        session,            // GS2 ログインセッション
        GachaPoolName,      // GS2-Gacha で作成したガチャプール名
        GachaName,          // GS2-Gacha で作成したガチャ名
        1                   // 何回目の抽選における排出確率を取得するか
    );

ここからは GS2-Gacha を採用するけれど、GS2-Showcase を使用しない場合の実装例を示します。
特別な理由が無ければGS2としては GS2-Showcase 経由での利用を推奨します。

ガチャ一覧の取得

    yield return gs2.Gacha.ListGachas(
        result => {
            if(result.Error != null) throw r.Error;
            // ガチャリストの取得に成功
            EzGachaList gachas = result.Result;
            foreach (var item : gachas)
            {
                Debug.Log("ガチャの名前: " + item.Name);
                Debug.Log("メタデータ: " + item.Meta);
                Debug.Log("抽選回数: " + item.DrawCount);
            }
        },
        session,            // GS2 ログインセッション
        GachaPoolName       // GS2-Gacha で作成したガチャプール名
    );

ガチャの取得

    yield return gs2.Gacha.GetGacha(
        result => {
            if(result.Error != null) throw r.Error;
            // ガチャの取得に成功
            EzGacha gacha = result.Result;
            Debug.Log("ガチャの名前: " + gacha.Name);
            Debug.Log("メタデータ: " + gacha.Meta);
            Debug.Log("抽選回数: " + gacha.DrawCount);
        },
        session,            // GS2 ログインセッション
        GachaPoolName,      // GS2-Gacha で作成したガチャプール名
        GachaName           // GS2-Gacha で作成したガチャ名
    );

ガチャを抽選する

    yield return gs2.Gacha.DoGacha(
        result => {
            if(result.Error != null) throw result.Error;
            EzPrizeList prizes = result.Result;
            foreach (var item : prizes)
            {
                Debug.Log("排出されたリソースID: " + item.ResourceId);
            }
        },
        session,            // GS2 ログインセッション
        GachaPoolName,      // GS2-Gacha で作成したガチャプール名
        GachaName           // GS2-Gacha で作成したガチャ名
    );

GS2-Gacha の利用料金

最後に料金についてですが、GS2-Gacha は完全IO課金となっており、

API呼び出し 1,000回あたり3円 に加え、以下の操作をしたときに追加の費用が発生します。

ガチャ一覧/ガチャ情報の取得 1円/1,000回
抽選処理 3円/1,000回
ガチャマスタのエクスポート 1円/回

それでは、また。

【新サービス提供開始】GS2-Showcase がご利用いただけるようになりました

みなさん、こんにちは。GS2の丹羽です。

先日発表した GS2-Showcase の提供を開始しましたので、お知らせします。

gs2.hatenablog.com

いつも通り、GS2-Showcase を Unity から使う方法を軽く説明したいと思います。

まず、商品情報の登録が必要です。
先日のブログエントリでも説明したとおり、商品には「商品」と「商品グループ」があり
それらを「陳列商品」として陳列することでショーケースができあがります。

これらは GS2 のマネージメントコンソールで登録して、JSON形式の設定ファイルをエクスポートすることができます。
JSON形式の設定ファイルですので、独自の管理ツールを作成して、そちらで作ったファイルで運用することも可能です。

設定ファイルを「ショーケースマスター」としてアップロードすることで、実際に商品情報を反映出来ます。


商品情報が登録出来たら、次は Unity から商品一覧を取得してみます。

yield return gs2.Showcase.DescribeSalesItems (
    result => {
        if(result.Error != null) throw result.Error;
        // 商品リストの取得に成功
        foreach (var item : result.Result)
        {
            Debug.Log("商品の種類: " + item.ItemType);
            Debug.Log("数量: " + item.ItemAmount);
            Debug.Log("通貨の種類: " + item.CurrencyType);
            Debug.Log("販売価格: " + item.Price);
        }
    },
    session,            // GS2 ログインセッション
    ShowcaseName,       // GS2-Showcase で作成したショーケース名
);

このようなコードを書くと、先ほど登録した商品情報が取得出来ます。
その際に、GS2-Schedule や GS2-Script で公開期間を設定していた場合は、期間外の商品は取得出来ません。
また、商品グループとして陳列した商品は条件を満たす1つの商品だけが結果に含まれます。


次に、商品を購入してみます。

yield return gs2.Showcase.BuyItem (
    result => {
        if(result.Error != null) throw result.Error;
        // 商品の購入に成功
        var stampSheet = result.Result; // スタンプシート
    },
    session,            // GS2 ログインセッション
    ShowcaseName,       // GS2-Showcase で作成したショーケース名
    itemId,             // DescribeSalesItems() で取得した商品ID
    KeyName             // 購入処理で使用する GS2-Key 暗号鍵名
);

購入したい商品の 商品ID と、購入処理で使用する「スタンプシート」の暗号化に使う暗号鍵を指定します。
スタンプシートの詳しい解説は以下のブログエントリを参照してください。

gs2.hatenablog.com


商品を購入すると、スタンプシートが発行されます。
この時点では対価などは消費されていませんし、購入したアイテムも付与されていません。
スタンプシートのタスクを実行することで、対価が消費されたり、購入したアイテムが付与されることになります。

なので、この後はスタンプシートのタスクを実行します。

stampSheet.OnCompleteTasks += () =>
{
    Debug.Log("購入した商品の種類: " + stampSheet.Item.ItemType);
    Debug.Log("入手した数量: " + stampSheet.Item.ItemAmount);
}

yield return stampSheet.RunTask (
    result => {
        if(result.Error != null) throw result.Error;
        // 全てのタスクを完了
    },
    session,            // GS2 ログインセッション
    KeyName,            // 購入処理で使用する GS2-Key 暗号鍵名
    new BuyConfig
    {
        StaminaMaxValue = 50,
    }                   // 購入時に使用するオプション値
);

スタンプシートには RunTask メソッドがあり、そちらを呼び出すことでタスクを実行出来ます。
エラーが発生すると、指定したコールバック関数にエラーが返ります。
エラーを気にせず、再び RunTask メソッドを呼び出すと、失敗したところから処理を再開することが出来ます。
リトライ回数をカウントしつつ、一定回数失敗したら諦めるような実装を推奨します。

スタンプシートの RunTask メソッドの引数で指定するコールバックの他に OnDoneTask / OnCompleteTasks といったコールバックを登録して待ち受けることも出来るようになっています。
扱いやすい方で購入完了処理をハンドリングしてください。


最後に料金についてですが、GS2-Showcase は完全IO課金となっており、

API呼び出し 1,000回あたり3円 に加え、以下の操作をしたときに追加の費用が発生します。

商品一覧/商品情報の取得 1円/1,000回
購入処理 3円/1,000回
商品マスタのエクスポート 1円/回

それでは、また。

【インタビュー記事】GameWith Magazine さんにインタビューしていただきました

みなさん、こんにちは。GS2の丹羽です。

本日は GameWith Magazine さんにインタビューをしていただいた記事が公開されましたので、お知らせします。

magazine.gamewith.co.jp

私とゲームの出会いや、なぜ GS2 という事業を始めたのか、これからどうなりたいのか。といった点を記事にしていただきました。
よろしければ、ご覧ください。

それでは、また。

【登壇情報】CEDEC2018 に登壇します

みなさん、こんにちは。GS2の丹羽です。

本日は、国内最大のゲーム開発者カンファレンスであるCEDECでの登壇が決まったことをお知らせします。

https://2018.cedec.cesa.or.jp/session/12018.cedec.cesa.or.jp

『サーバレスアーキテクチャによるゲームサーバ開発』という題目で、サーバレスアーキテクチャとは何か?といった初歩的な内容から
サーバレスアーキテクチャをゲームに応用することでどのような恩恵が得られるかをお話しさせていただきたいと思います。

https://2018.cedec.cesa.or.jp/2018.cedec.cesa.or.jp

CEDECパシフィコ横浜 で 2018.08.22 (水) - 08.24 (金) の期間開催される予定です。
ご参加なさる際には、GS2のセッションにも是非足をお運びいただければ幸いです。

それでは、また。

マイクロサービス間でトランザクション処理を行う

みなさん、こんにちは。GS2 の丹羽です。

本日 GS2-Showcase という新サービスを告知しました。
gs2.hatenablog.com

このサービスを開発するにあたって新しいトランザクションシステムを導入することにしました。
このトランザクションシステムを GS2 内ではスタンプラリーと呼ぶことにしています。

マイクロサービスにおけるデータ更新の課題

まず、最初にマイクロサービス内におけるデータ更新の課題について振り返ってみます。
マイクロサービス間の結合度を下げる為には、まずは依存関係をなるべく少なく保つ必要があります。

たとえば、今回発表した GS2-Showcase を実装するためには最大4つのシステムが連携することになりました。
代表的な例として、課金通貨を使用してゲーム内通貨を購入するケースで必要となる操作を整理します。

  • GS2-Showcase / 商品が陳列されている(販売期間内である)
  • GS2-Money / 消費する通貨が商品価格に対して十分である
  • GS2-Gold / 購入する通貨が購入後もウォレットの上限に達しない
  • GS2-Limit / 商品の購入回数をカウントアップする
  • GS2-Money / 通貨を消費する
  • GS2-Gold / 通貨を加算する

このようなアクションを同期的に実行しなければ GS2-Showcase の機能を満足に提供することは出来ません。
しかし、マイクロサービス間では異なるデータベースを持ちますし、何らかの方法で排他処理を実装する必要がありました。

スタンプラリー

そこで、GS2 では新たにスタンプラリーというトランザクションシステムを用意しました。
スタンプラリーには以下の概念が存在します。

スタンプシート

スタンプラリーを実行する単位です。
スタンプシートには複数のスタンプタスクと、スタンプラリーを完走したときに得られる報酬。報酬を得るためのエンドポイントが記録されています。

スタンプタスク

スタンプタスクはスタンプラリーの報酬を得るために起こさなければならないアクションが記録されています。
スタンプタスクは主にスタンプラリーを完走したときに得られる報酬を得るための対価を支払うアクションの定義となります。

例を分類

先ほどの例をスタンプラリーの概念で分類してみます。

状態保証

  • GS2-Showcase / 商品が陳列されている(販売期間内である)
  • GS2-Money / 消費する通貨が商品価格に対して十分である
  • GS2-Gold / 購入する通貨が購入後もウォレットの上限に達しない

状態保証はスタンプラリーを開始するために必要となる条件です。
今回は GS2-Showcase がスタンプシートを発行することになりますので『GS2-Showcase / 商品が陳列されている(販売期間内である)』に関する保証は容易です。
GS2-Showcase では商品の購入アクション実行時(スタンプシート発行直前)に GS2-Script を呼び出すことが出来ます。
このスクリプト内で『GS2-Money / 消費する通貨が商品価格に対して十分である』『GS2-Gold / 購入する通貨が購入後もウォレットの上限に達しない』を検証することで状態保証を行えます。

さらに、スタンプラリー実行中に状態が変化しないことを保証する為に GS2-Money / GS2-Gold のウォレットに対してロックを取得するといいでしょう。
その際に、その後の通貨の消費や加算処理の妨げにならないよう、スクリプトにはスタンプラリーにおいて使用するトランザクションIDが渡りますので、それを使用して GS2-Lock でロックを取得します。

ウォレットが条件を満たしていない場合や、ロックの取得に失敗した場合はスクリプトからエラー応答をすることで、スタンプシートの発行を止めることが出来ます。

変化要求

  • GS2-Limit / 商品の購入回数をカウントアップする
  • GS2-Money / 通貨を消費する

次に、変化要求です。
スタンプシートのスタンプタスクを全て実行することで変化要求に応えることが出来ます。
スタンプタスクは実行されたかという状態をサーバ側で管理しており、複数回実行出来ないようになっています。
『GS2-Limit / 商品の購入回数をカウントアップする』と『GS2-Money / 通貨を消費する』はそれぞれのマイクロサービスにタスクを送信することで、実行出来ます。
仮に処理が失敗した場合もリトライをしたり、場合によってはロールバックしましょう。

報酬

  • GS2-Gold / 通貨を加算する

スタンプラリーを終えたら、スタンプシートを消費することで、報酬が得られます。
指定されたエンドポイントにスタンプシートを送信すると、全てのタスクが完了しているかを検証し、問題が無ければ報酬を付与してスタンプシートを無効化します。

最後にスタンプシートに設定された、スタンプシートを消費したときに呼び出される GS2-Script でロックを解除すれば処理は終わりです。

不正対策

ゲームに不正行為はつきものです。スタンプラリーではどのような不正対策をおこなっているのでしょうか。

署名

スタンプタスク毎/スタンプシート全体 に署名がつけられています。
これによって、スタンプタスク内に含まれる 対価の消費数量 や、スタンプシートに含まれるタスクの数や種類を差し替えようとしても出来ないようになっています。

スタンプシートの無効化

報酬を得たスタンプシートはその時点で無効化しているため、全てのタスクを終えた1つのスタンプシートを使って何度も報酬を得ることは出来ません。

状態保証の不正取得

変化が起きる前にスタンプシートを何度も取得して購入回数制限などを突破しようとしたとします。
この場合、GS2-Lock を使用してリソースのロックを取得している場合は、2回目以降はそのロックが取れずに失敗します。
仮に GS2-Lock を使っていなかったとしても、GS2-Limit で購入回数をカウントアップするタスクを実行する際に不正に取得したスタンプシートでは回数上限に達してしまいタスクを完了出来ないため、報酬を得ることも出来ません。

スタンプシートの特徴

スタンプタスクを実行する際には、誰が何のためにタスクを実行しようとしているのか、消費されるマイクロサービスは知る必要がありません。
『スタンプシートを発行出来るのは信頼出来るシステムからに限定されている』という前提で信頼してタスクを実行します。

スタンプシートを消費して報酬を付与する際も同様で、誰が何の前提処理をして報酬を付与しているのかを、報酬を付与する側のマイクロサービスは知る必要がありません。

この信頼関係を前提として、各マイクロサービスはタスク・シートを処理することで、疎結合ながらも一貫したデータ更新が行えます。

スタンプシートの課題

スタンプシートは特性上、報酬は1つのマイクロサービスに対して行う必要があります。
そのため、複数のマイクロサービスに影響を与える報酬を同期的に処理することは出来ません。

GS2 では複数の報酬があるものに関しては GS2-JobQueue を使用したジョブを報酬毎に登録することで、結果整合で報酬が付与される仕組みで対応する予定です。

それでは、また。

【新サービス】ショップ機能を提供する GS2-Showcase を発表

みなさん、こんにちは。GS2 の丹羽です。

今日は近日公開予定の新サービス GS2-Showcase を発表します。
GS2-Showcase はいわゆるショップ機能を提供するものです。

これまで GS2-Money をご利用いただいている皆様の実装傾向を見ていると
初回のみ安く課金通貨が購入出来るような仕組みを提供されていることが多数見受けられました。
しかし、これまでの GS2-Money では全ての購入可能なの商品情報を応答するのみで、
そのような仕様には対応出来ておらず、おそらくゲーム側で商品情報をフィルタリングするなど苦労をおかけしていたと推察します。

GS2-Showcase はそのような課題を解決するためのサービスで、次のような特徴があります。

商品の公開時期を設定可能

商品を公開する時期を GS2-Schedule のイベントと連動させることが出来ます。

購入数量の制限を設定可能

商品は GS2-Limit と連動することで購入可能な回数を設定出来ます。

商品グループを設定可能

グループ内で優先度が高い順に購入可能かを判断し、購入可能な1つだけが商品として陳列される機能です。
初回半額で購入出来る商品を購入した場合に、通常価格の商品を表示するようにしたい。というような仕様に対応できます。

他のGS2サービスと連携可能

購入通貨として使用可能

  • GS2-Money(ストア決済)
  • GS2-Money(有償課金通貨)
  • GS2-Money(有償/無償課金通貨)
  • GS2-Gold

商品として陳列可能

  • GS2-Money(課金通貨)
  • GS2-Gold
  • GS2-Stamina
  • GS2-ConsumableItem

連携対象のサービスは今後も随時追加してきます。

それでは、また。

Startup Architecture of the year 2018 で オーディエンス賞 をいただきました #AWSSummit

みなさん、こんにちは。GS2の丹羽です。

f:id:kazutomo:20180604100426p:plain

先週末に開催されました、AWS Summit Tokyo 2018 で開催された Startup Architecture of the year 2018 でオーディエンス賞をいただきました。

f:id:kazutomo:20180604100826p:plain

このオーディエンス賞は AWS Summit 会期中に受付付近にファイナリストのアーキテクチャ図のパネルが設置されており、
来場者が「これはいい」と思ったアーキテクチャのシステムの横に設置された AWS IoT Button を押すことで投票出来る。というものでした。

Game Server Services は以下のパネルを設置していました。

f:id:kazutomo:20180604100922p:plain

来場者のみなさんに数多くの支持をいただいたことで、この賞を受賞出来たということで、ただただ感謝しかありません。
会場で GS2 に投票いただいた皆さんにお礼申し上げます。

今後も先進的な技術で、より便利なサービスを提供出来るよう頑張りますので、応援よろしくお願いします。

それでは、また。

(C) Game Server Services, Inc.