メインコンテンツに移動
デベロッパーのためのクラウド活用方法
AWS for Games logo featuring a white game controller icon and the text 'AWS FOR GAMES'.

魔法で作る Amazon DynamoDB の 簡単ゲームインベントリ

2023-01-05 | Author : Sheng Hsia Leng, 石井 宇大

はじめに

ゲームな皆さんこんにちは、Game Solutions Architect の Leng (@msian.in.japan) と Game Developer Relations の Taka (@takahiroishii_) です。

この投稿ではゲームのバックエンドを初めてクラウド化させようと考えていて、オンラインゲームを作成する上で Amazon DynamoDB のデータ設計の基礎を学んでみたい、もしくは DynamoDB をゲームから学びたい、そんな皆さんが読んですぐにゲームデザインに合ったテーブル設計ができる事を目指した魔法のような記事になります。


X ポスト » | Facebook シェア » | はてブ »

builders.flash メールメンバー登録

毎月提供されるクラウドレシピのアップデート情報とともに、クレジットコードを受け取ることができます。 
今すぐ特典を受け取る »

AWS for Games

AWS for Games ではより早い開発、よりスマートな運営、そしてより楽しいゲームへの成長という Build、Run、Grow の 3 つの柱に沿ってサポートします。本日は Run の柱、そして ゲーム向けデータベース のお話になります。
A diagram showing the stages of game development using AWS: Build (クラウドゲーム開発), Run (ゲームサーバー, ゲームセキュリティ, ゲーム向けデータベース), and Grow (LiveOps, ゲーム分析, AI & ML), with Japanese text and relevant icons.

Amazon DynamoDB とゲーム

Amazon DynamoDB はハイパフォーマンスなアプリケーションを様々な規模で実行できる、フルマネージドでありサーバーレスでもある Key-Value 型の NoSQL データベースです。そんな DynamoDB とゲームの相性を考えてる上でまずは DynamoDB の代表的な特徴をあげます

  • Key-Value データベース : キーと値というシンプルな管理方法でデータを格納
  • 高いスケーラビリティ : 一貫性のある高速パフォーマンスを自動でスケールしながら実現
  • 低い管理負担 : バージョンアップやメンテナンスのような作業が不必要


次にそれぞれの特徴とゲームの相性を見ていきましょう

  • Key-Value データベース : プレーヤー主体であるゲームのデータベースのキーはほとんどがプレーヤー ID
  • 高いスケーラビリティ : 突然人気が出たり、時間帯で総プレーヤー数が著しい変化するのがゲーム
  • 低い管理負担 : 管理負担を減らす事でゲーム本来の面白さを作る事に集中できる


どの DynamoDB の特徴もゲームと非常にマッチしていて高いシナジーがある事がわかります。

Amazon DynamoDB のコンポーネント

この記事では DynamoDB の基本的な機能にフォーカスし、テーブル設計をより簡単にイメージできる事を目指します。その中で出てくるいくつかの DynamoDB のコアコンポーネント があるので先に確認しておきましょう !

  • テーブル (Table) : RDB や他のデータベース同様、データのコレクションをテーブルと呼びます
  • 項目 (Item) : 各テーブルに入っている識別可能な属性のグループです。RDB でいう行にあたります
  • 属性 (Attribute) : 各項目は1つ以上の属性で構成されます。RDB でいう列にあたります


次に Key-Value 型である DynamoDB の Key の部分に当てはまるコンポーネントです。各テーブルはキーを指定して作る必要があり、そのテーブル内の 2 つの項目が同じキーを持つことはありません。このキーをプライマリキー (Primary Key) と呼びます。
更に、DynamoDB は 2 種類の異なるプライマリキーをサポートします。

  • パーティションキー (Partition Key) : パーティションキー、通称 PK という1つの属性で構成されたシンプルなプライマリキー
  • パーティションキーとソートキー (Sort Key) の組み合わせ : PK とソートキー、通称 SK という2つの属性で構成された複合プライマリキー


シンプルな Key-Value として 1 つの属性でプライマリキーを作り管理する事も多いですが、2 つのキーである PK と SK を組み合わせる事で同じ PK に複数の SK を紐付け複数の項目を持たせるケースも様々場面で便利になります。

この他にも Amazon DynamoDB は沢山の機能を持ち合わせています。詳しくは 公式ドキュメント を参照してください!

ゲームインベントリの定義

では早速ゲームインベントリを DynamoDB で作る準備をしたいと思います。まず今日作るゲームのインベントリとは何を指すのか、どんな物を管理するのか、そしてどういった管理方法があるのか確認していきます。
Cartoon illustration of a wizard in a yellow robe and hat, surrounded by pixel-style inventory icons including clothing, a staff, book, mushroom, and ring, with 'AWS for Games' branding in the corner.

ゲームインベントリ

一般的にゲームインベントリとは、そのゲーム内でにあるアイテムを管理する場所を指します。例えば、RPG のようなゲームの場合プレーヤーが操作できる各キャラクターが武器・アクセサリー・防具などを管理するインベントリを持っていたり、はたまたターン制の戦略対戦ゲームなどでは各プレーヤーが複数のキャラクターとそれぞれのキャラクターに紐付いた武器や防具を管理するインベントリを持っているといった場合があるでしょう。今回は後者のようなプレーヤーが 1 つだけ持っているインベントリを作成していきたいと思います。

オンライン対戦機能のついたゲームの場合クラウド上にサーバーを置く事は必然的になり、またオフラインメインのゲームでもインベントリをクラウド上に保存し管理する事でプレーヤーのデータが守られ、マルチプラットフォームな環境でも簡単にプレーヤーは遊ぶ媒体を変更する事ができます。このように様々な理由でゲームのクラウド化を考える方は少なくないでしょう。

管理の少ない DynamoDB だからこそ、普段は手をかける事なくプレーヤー体験を向上させる事ができるというのも大きな利点になります。そんな DynamoDB という武器を持った魔法使いになって、ゲームをあっという間に作っちゃいましょう !

Diagram illustrating the relationships between players, characters, and weapons in a game inventory system using AWS DynamoDB. The image features a player figure, multiple characters (witch, demon, knight), and various weapons (staff, axe, sword), representing how players can have different characters and weapons. Includes an 'AWS for Games' logo.

ゲームスタート !

前置きが少し長くなりましたが、いよいよ作業を開始したいと思います !

DynamoDB のテーブル設計をしていく上で ”アクセスパターンからテーブルは設計する” といったアドバイスを聞いた事のある方も多いでしょう、実際に公式ドキュメントにも 2 つの重要な概念 の1つとして紹介されています。いまいちこの概念の意味が理解できない方や初めて聞いたという方もご安心ください ! ここからは皆さんが慣れているゲーム開発のフローに合わせて紹介させていただきます。

テーブル設計までの流れ

ゲームに置けるアクセスパターンとはずばり、ゲームデザインです。ゲームデザインとはゲームを面白くさせるために様々なアイディアを出しどんなゲームになるか設計していく作業の事です。テーブルを設計していく前にまずは、何を管理するのか、どんな情報が必要か、その情報を取得したり付与するゲームの UI/UX はどんな物になるのか、その UI/UX を支えるのに必要な API はどんな物になるのか、といった内容を考え決定した後にテーブル設計に取り組みます。
A flow diagram showing the inventory design process for games using AWS DynamoDB, with Japanese text. Steps include deciding inventory contents, API design, and table design, with a cartoon wizard character and 'AWS for Games' logo.

ゲームデザインを決める

インベントリで管理する物その 1 : キャラクター

インベントリの中に入れる物その1はキャラクターです。ターン制の戦略対戦ゲームをイメージしているので 1 人のプレーヤーが複数のキャラクターを保持できます。それでは各キャラクターに紐付いている情報を決めます

  • 持ち主であるプレーヤーの ID

  • このキャラクターのユニークな ID (全空間でユニーク)

  • このキャラクターの名前 (ユニークである必要なし)

  • このキャラクターのデータ ID (例えばマスターデータの ID )


プレーヤー ID 及びプレーヤー情報はすでに何かしらの方法で管理されているものとします。


インベントリで管理する物その 2 : 武器

インベントリの中に入れる物その 2 は武器です。こちらもキャラクターと同じく 1 人のプレーヤーが複数の武器を保持できます。それでは各武器に紐付いている情報を決めます。

  • 持ち主であるプレーヤーの ID

  • この武器のユニークな ID (全空間でユニーク)

  • この武器の名前 (ユニークである必要なし)

  • この武器のデータ ID (例えばマスターデータの ID )


繰り返しになりますが、プレーヤー ID 及びプレーヤー情報はすでに何かしらの方法で管理されているものとします。


キャラクターに関する API

ゲームの UI/UX を思い浮かべ、その UI/UX に必要な必要な API を決めます。

GET : /characters/playerId
ある1人のプレーヤーの全てのキャラクターを取得する API

GET : /characters/character/playerId/characterId
ある1人のプレーヤーのある 1 つのキャラクターを取得する API

POST : /characters/new/playerId/characterDataId
ある 1 人のプレーヤーにマスターデータに基づきある 1 つキャラクターを付与する API


武器に関する API

キャラクター同様に武器に関しても基本的な作業を UI/UX 上で行う上で必要な API を決めます。

GET : /weapons/playerId
ある 1 人のプレーヤーの全ての武器を取得する API

GET : /weapons/weapon/playerId/weaponId
ある 1 人のプレーヤーのある 1 つの武器を取得する API

POST : /weapons/new/playerId/weaponDataId
ある 1 人のプレーヤーにマスターデータに基づきある 1 つ武器を付与する API

テーブル設計

では早速この定義された内容からテーブルを設計していきたいと思います。ひとまず管理したい情報は 2 種類 (キャラクターと武器) あったのでそれぞれバラバラに設計していきます。設計の手順は同じで以下の順番で設計していきます。

  • まずはテーブルの名前を決める
  • PK を考える
    • 誰/何に紐付いている情報でか考える
  • SK が必要か考える
    • PK だけで管理できそうか考える
  • 最後に残りの情報を何も考えないで属性として全部入れてしまう !

キャラクターの情報を管理するテーブル

ゲームデザインを振り返りながら、そしてテーブル設計の手順に沿いながらキャラクターの情報を管理するテーブルを設計していきます。

まずはテーブルの名前を決める
テーブルの名前は、そうですね、キャラクターを管理するという事で、ズバリ Characters にしましょう !

PK を考える
キャラクターの情報は何に紐付いているでしょう ? 各キャラクターには持ち主であるプレーヤーいてそのプレーヤーにはプレーヤー ID があるはずです。なので PK は持ち主であるプレーヤーの ID、 playerId にします !

SK が必要か考える
PK だけで管理できるかゲームデザインを振り返ってみます。
1 つ目の API “ある 1 人のプレーヤーの全てのキャラクターを取得する API” これを言い換えると、”プレーヤー ID でそれに紐付いているキャラクター全部持ってくる” になります。すでに PK がプレーヤー ID なので、この API は SK がなくても実現が可能です。2 つ目の API は “ある 1 人のプレーヤーのある 1 つのキャラクターを取得する API” これを言い換えると “プレーヤー ID に紐付いている特定のキャラクターを持ってくる” になります。この API を完成させるには、プレーヤー ID だけじゃなくキャラクターを特定する何かを使う必要があります。結論に行く前に、先に 3 つ目の API も確認しましょう、3つ目の API はプレーヤーにキャラクターを付与する API なので送る情報さえ足りていれば特に要件は無さそうです。
SK が必要かどうかに戻ると、2 つ目の API を満たすためには SK にキャラクターの固有の情報を使い PK と SK の複合プライマリキーで取得できると分かります。更にゲームデザインを深堀りするとキャラクターの情報の中にはキャラクターのユニークな ID がありました、これが使えそうですね ! という事でズバリ SK を characterID にしましょう !

最後に残りの情報を何も考えないで属性として全部入れてしまう !

ここは NoSQL の強み ! 残りの情報であるキャラクターの名前とキャラクターのデータ ID はそのまま入れてしまいます ! それぞれ characterNamecharacterDataId と命名しましょう。

これらをまとめ呪文を唱えると以下のようなテーブル Characters が完成すると思います。例となるデータも入れてみました。

A schema diagram for an AWS DynamoDB table representing game characters. The diagram shows the primary key composed of a partition key (playerId) and a sort key (characterId), with character attributes such as characterName and characterDataId. Illustrated examples include a player, a mage character, and attribute values. The diagram includes English and Japanese text along with a game controller icon and AWS for Games logo.

武器の情報を管理するテーブル

武器の情報を管理するテーブルを設計していきますが、ゲームデザインを見ていると気づいた方も多いと思います、武器のゲームデザインはキャラクターのゲームデザインと非常に似ています。同じ手順で同じように進めるので割愛し、魔法を使って一瞬で設計します。
A diagram illustrating an example table schema for game weapons in Amazon DynamoDB, showing primary key structure with partition key (playerId), sort key (weaponId), and attributes (weaponName and weaponDataId) with sample values. Includes bilingual labeling (Japanese and English) and a visual game-themed design.

完成。。。?

いやー完成しましたね ! と思っているあなたもう一声です ! ゲームデザインからテーブルを設計する事は DynamoDB に置ける 2 つの重要な概念 の内の最初の 1 つでした。言わば、まだ敵の HP が半分残っているような状態です。この概念のもう 1 つが ”テーブルはできるだけ少なくする” です。今回管理している情報である、キャラクターそして武器、それぞれに 1 テーブルづつ作成している事は一見できるだけ少なくした状態に見えます。ですが改めてゲームデザインそして 2 つのテーブルを見てみると、アクセスパターンは類似していて、テーブルのスキーマも非常に類似しています。これを上手く 1 つに纏めることはできないでしょうか ?

一度そのまま合わせて見たいと思います。テーブルの名前は Inventory とし、キャラクターと武器両方に共通していた SK の名前はどちらでもないので思い切って sk という名前にします。実は DynamoDB ではこのように PK や SK を中身に影響されずに使いまわしがきくようにそのまま PK/SK という名前にするテクニックがあります。

上手く纏めれてスッキリしたように見えますね ! ですが、念の為ゲームデザインを振り返って見ましょう。例えば、キャラクター管理の API の1つ目 “ある 1 人のプレーヤーの全てのキャラクターを取得する API” を引き続き使う事はできるでしょうか ?

キャラクター専用のテーブルがあった場合は PK のプレーヤー ID だけでデータを取得する事で全てのキャラクターが取得可能でした。しかし、1 つのテーブルに纏めた事で同じ方法を取ると全てのキャラクターと全ての武器を取得してしまう事が分かります。いやーこまりましたね。

A visual diagram illustrating an example DynamoDB table for a game's inventory system, showing primary key, partition key (playerId), sort key (sk), and attributes such as characterName, characterDataId, weaponName, and weaponDataId.

begins_with

ここで使える魔法が DynamoDB のクエリのキー条件式 の 1 つである begins_with という条件式です。begins_with は SK がある特定のサブ文字列から始まる事を条件に絞り込みができるとても便利な条件式です。この条件式を使ってゲームデザインの要件であった “ある 1 人のプレーヤーの全てのキャラクターを取得する API” を満たすために、全てのキャラクターの ID を character_ というサブ文字列で始め、武器の ID を weapon_ というサブ文字列で始めたいと思います。それを踏まえたテーブルとテーブルの中身の例がこちらになります。

Diagram illustrating an example of a DynamoDB inventory table for games, showing primary key structure, partition key (playerId), sort key (sk), and item attributes for a player's character and weapon. Includes labeled columns, attributes, and example data for a game player.

拡張性

テーブルをできるだけ少なくした事で管理が用意になっただけでなく、拡張性も追加されました。1 つの拡張性がインベントリの中身であるキャラクターと武器を 1 人のプレーヤーに対して全てを取得する必要が出てきた際に、PK であるプレーヤー ID を指定するだけでキャラクターも武器も同時に取得可能になりました。

さらに、今回は紹介しなかった DynamoDB の他のコンポーネントであるセカンダリインデックスを利用する事で、例えばキャラクターと武器それぞれに闇耐性のような特性 (passive) がある場合、それらもテーブルの属性として追加し、passive をグローバルセカンダリインデックスの SK として登録し、playerId を引き続きグローバルセカンダリインデックスでも PK とすることで “ある1人のプレーヤーの全闇耐性のキャラクターと武器を取得する” といった新しいゲームデザインの要件を満たす事ができます。

こうする事で、プレーヤー ID に紐付いた全キャラクターを取得する時は playerId = player1 and begins_with(sk, "character_") という条件を、はたまた全武器の取得する時は playerId = player1 and begins_with(sk, "weapon_") という条件を使う事でゲームデザインの要件を満たすことができます。

これでゲームデザインに含まれる全ての情報を管理し、全ての API をサポートする 1 つの単一のテーブルが完成しました !

Diagram illustrating a game inventory table structure in AWS DynamoDB, showing partition key (playerId), sort key (sk), and item attributes for characters and weapons, with sample data for a player and usage of GSI keys. Includes icons and some Japanese labels.

拡張性

テーブルをできるだけ少なくした事で管理が用意になっただけでなく、拡張性も追加されました。1 つの拡張性がインベントリの中身であるキャラクターと武器を 1 人のプレーヤーに対して全てを取得する必要が出てきた際に、PK であるプレーヤー ID を指定するだけでキャラクターも武器も同時に取得可能になりました。

さらに、今回は紹介しなかった DynamoDB の他のコンポーネントであるセカンダリインデックスを利用する事で、例えばキャラクターと武器それぞれに闇耐性のような特性 (passive) がある場合、それらもテーブルの属性として追加し、passive をグローバルセカンダリインデックスの SK として登録し、playerId を引き続きグローバルセカンダリインデックスでも PK とすることで “ある1人のプレーヤーの全闇耐性のキャラクターと武器を取得する” といった新しいゲームデザインの要件を満たす事ができます。

Diagram illustrating a game inventory table structure in AWS DynamoDB, showing partition key (playerId), sort key (sk), and item attributes for characters and weapons, with sample data for a player and usage of GSI keys. Includes icons and some Japanese labels.

まとめ

ゲームの裏側として採用が増えている Amazon DynamoDB、その難しいと思われがちがテーブル設計をゲームデザインを元にゼロからやってみました。

今回ご紹介した DynamoDB のゲームでの活用例やその他のデータベースに関した様々な情報がゲーム開発者の皆さん向けに AWS for Games のゲーム向けデータベース のページで纏めて確認できるようになっています。是非皆さんのゲームにあったデータベースを選んで楽しいゲーム開発に役立てて下さい !

筆者プロフィール

Anime-style illustration of a girl with big eyes, brown hair, and a pink shirt, set against a green background.

Sheng Hsia Leng

アマゾン ウェブ サービス ジャパン合同会社
ソリューションアーキテクト

ゲーム業界に特化したソリューションアーキテクトとしてお客様を支援しております。
RPG とドット絵ゲームが好きです。オフモードの時はインスタでバイリンガル漫画を投稿しています。

A man standing outdoors in front of a tree, wearing a white and gray striped t-shirt, smiling at the camera.

石井 宇大

アマゾン ウェブ サービス ジャパン合同会社
ゲームデベロッパーリレーションズ

カナダ🇨🇦 で 10 年以上生活していたゲームで遊ぶのも作るのも好きな元ゲームエンジニア。趣味は奥さんと季節を感じながら美味しい物を食べ大好きな赤🍷 を嗜む事。
普段は楽しいゲーム作りに繋がるよう、様々なソリューションを提供するお仕事をしています。