11. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
開発規模と更新頻度を柔軟に変えられる仕組み
10
モバイルゲームの開発環境に求められるのは
開発環境のスケーラビリティ
12. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
1. 使用技術
2. データベーススキーマ管理
3. マスタデータ管理
4. 開発サーバ管理
11
アジェンダ
13. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
1. 使用技術
2. データベーススキーマ管理
3. マスタデータ管理
4. 開発サーバ管理
12
アジェンダ
14. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
サーバ
.NET Core (C#)
GCP
Google Kubernetes Engine
Cloud Spanner
Memorystore for Redis
など
クライアント
Unity (C#)
※このセッションは(一部を除き)使用技術に依らない内容です
13
新規開発プロジェクトでの使用技術
15. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
1. 使用技術
2. データベーススキーマ管理
3. マスタデータ管理
4. 開発サーバ管理
14
アジェンダ
16. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
マスタテーブル
ゲーム内で不変のデータを保存
例)どのようなクエストがあって、
どの敵が出現するか
15
テーブルの種類
ユーザテーブル
ゲーム内で可変のデータを保存
例)クエストをどこまで進めたか、
どのアイテムをいくつ持っているか
これらのテーブル構造を定義するのがデータベーススキーマ(以下、DBスキーマ)
17. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
DBスキーマにまつわる情報は、意外なほど多い
O/Rマッピング用クラス、DBアクセス用クラスなどなど
開発環境のスケーラビリティを実現するために
開発規模を意識して
DBスキーマを一元管理し、情報を散在させない
更新頻度を意識して
DBスキーマ変更にかかるコストを最小限にする
16
DBスキーマ管理のポイント
DBスキーマにまつわる情報の自動生成を徹底
18. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved. 17
O/Rマッピング用クラスとDDLを自動生成
▼データベース設計書
CREATE TABLE user (
user_id STRING(36),
name STRING(MAX),
updated_at INT64,
created_at INT64,
) PRIMARY KEY (user_id);
/// <summary>
/// アカウント情報を保存するテーブル
/// </summary>
public partial class UserRecord : BaseRecord
{
/// <summary>
/// ユーザを一意に識別するID(GUIDv4)
/// </summary>
public Guid UserId { get; set; }
/// <summary>
/// ユーザ名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 更新日時
/// </summary>
public DateTime UpdatedAt { get; set; }
/// <summary>
/// 作成日時
/// </summary>
public DateTime CreatedAt { get; set; }
}
◀コメントも出力
自動生成
19. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved. 18
DBアクセス用クラスも自動生成
▼手動更新ファイル(最初の1回のみ生成)
/// <summary>
/// アカウント情報を保存するテーブル
/// </summary>
public partial class UserModel : UserDataModel
{
/// <summary>
/// 1レコードをINSERTする
/// </summary>
/// <param name="valueRecord">INSERTするレコード</param>
/// <returns></returns>
public Task<UserRecord> InsertAsync(UserRecord valueRecord)
{
return InsertAsync<UserRecord>(valueRecord);
}
/// <summary>
/// 1レコードをUPDATEする
/// </summary>
/// <param name="valueRecord">UPDATEする値を設定したオブジェクト</param>
/// <returns></returns>
public Task<UserRecord> UpdateAsync(UserRecord valueRecord)
{
return UpdateAsync<UserRecord>(valueRecord);
}
......
......
}
/// <summary>
/// アカウント情報を保存するテーブル
/// </summary>
public partial class UserModel
{
}
▼自動更新ファイル(毎回生成)
20. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved. 19
マスタテーブルも自動生成
CREATE TABLE mst_item (
id INT64,
name STRING(MAX),
) PRIMARY KEY (id);
/// <summary>
/// アイテムを定義するマスタテーブル
/// </summary>
public partial class MstItemRecord : BaseRecord
{
/// <summary>
/// アイテム ID
/// </summary>
public int Id { get; set; }
/// <summary>
/// アイテム 名
/// </summary>
public string Name { get; set; }
}
自動生成
▼データベース設計書
21. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved. 20
定数も自動生成
/// <summary>
/// アイテムの種類
/// </summary>
public enum ItemType : int
{
/// <summary>
/// 経験値アイテム
/// </summary>
[Description("経験値アイテム")]
EXP = 1,
/// <summary>
/// イベントアイテム
/// </summary>
[Description("イベントアイテム")]
EVENT_ITEM = 2,
}
/// <summary>
/// アイテムを定義するマスタテーブル
/// </summary>
public partial class MstItemRecord : BaseRecord
{
/// <summary>
/// アイテム ID
/// </summary>
public int Id { get; set; }
/// <summary>
/// アイテム 名
/// </summary>
public string Name { get; set; }
/// <summary>
/// アイテムの種類
/// </summary>
public ItemType Type { get; set; }
}
▲Description属性はデバッグ機能の
選択肢表示などで使用
(定数の意味を一元管理)
▼データベース設計書
▼定数定義
22. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved. 21
ALTER TABLEも自動生成(Rollback用も)
ALTER TABLE mst_item ADD COLUMN event_id INT64;
ALTER TABLE mst_item DROP COLUMN event_id;
1.0.0-1599195600.sql
rollback¥1.0.0-1599195600.sql
差分を取って出力
▼前回出力した設計書 ▼今回出力する設計書
23. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
ALTER TABLEのファイル名にはアプリバージョンとtimestampを使用
22
DDLのバージョン管理
1.0.0-1599195600.sql
【アプリバージョン】
アプリをバージョンアップするタイミン
グでスキーマ変更することが多いため
「あるバージョンのアプリをリリースす
る時に、どのスキーマを適用するか」が
わかりやすい
【timestamp】
複数人が別々の開発ブランチで並行
してスキーマ変更できるように
ブランチA ブランチB
1.0.0-1599195600.sql 1.0.0-1599800400.sql
マージ
ALTER TABLE mst_item ADD COLUMN event_id INT64; ALTER TABLE mst_quest ADD COLUMN event_id INT64;
24. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
各開発環境ごとに「どのALTER TABLEファイルを反映済みか」を保存
開発サーバデプロイ時に、未反映のSQLファイルを内製のマイグレートツールで自動反映
23
開発環境でのDDL管理
edition
1.0.0-1599195600
database_edition
edition
1.0.0-1599195600
1.0.0-1599800400
database_edition
デプロイ
+
スキーマ
マイグレート
25. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved. 24
yamlのスキーマ定義も自動生成
mst_item:
primary_key: [id, ]
foreign_key:
event_id: mst_event
range:
regular_expression:
columns:
- name: id
type: decimal
type_detail:
- name: name
type: string
type_detail:
- name: type
type: decimal
type_detail: ItemType
- name: event_id
type: decimal
type_detail:
マスタデータ周りのツールで使用(後ほど解説)
ItemType:
mapping:
EXP: 1
EVENT_ITEM: 2
▼type.yaml
▼schema.yaml
▼データベース設計書
▼定数定義
26. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved. 25
クライアント側のファイルも自動生成
/// <summary>
/// アイテムを定義するマスタテーブル
/// </summary>
public partial class MstItemRecord : BaseRecord
{
/// <summary>
/// アイテム ID
/// </summary>
public int Id { get; set; }
/// <summary>
/// アイテム 名
/// </summary>
public string Name { get; set; }
/// <summary>
/// アイテムの種類
/// </summary>
public ItemType Type { get; set; }
}
サーバ
GitHub
クライアント
GitHub
自動生成 PR作成
データベース設計書
クライアント側でも使用するマスタデータ、ユーザデータ用のクラス
27. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
DBスキーマに関するファイルは自動生成を徹底
DBスキーマ変更作業の属人化を防止
並行作業にも対応
突発的なスキーマ変更でも抜け漏れなく対応可能
開発サーバのDBスキーマの状態を厳密に管理
サーバプログラムとDBスキーマが一致するように自動更新
26
ここまでのまとめ
28. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
1. 使用技術
2. データベーススキーマ管理
3. マスタデータ管理
4. 開発サーバ管理
27
アジェンダ
32. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
ゲームの仕様によるため
実際に運用してみてから気づく「使いづらさ」があるため
マスタデータ入力を始める段階で仕組みを導入できている必要があるため
開発後半で抜本的に仕組みを変えるのは、なかなか難しい
開発者の好みにもよるため
31
なぜ最適解がないのか
33. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
開発環境のスケーラビリティを実現するために
開発規模を意識して
マスタデータ作成を並行作業できるようにする
可能な限り自動化する
リリースタイミングを可視化する
更新頻度を意識して
マスタデータの段階的なリリースのハードルを下げる
32
マスタデータ管理のポイント
37. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
(本当は)入力ツールの内製が一番
ゲーム特有の機能を持たせられる
クエストや敵のデータを楽に作れたり
開発ツールと連携してイテレーションを早くできたり
データチェック機能を持たせたり
しかし…
以下を理由に、まだ手を出せないと判断
中途半端なものを導入したら逆効果
ゲーム特有の機能を持たせると、仕様変更や機能追加にかかるメンテナンスコストが多い
(将来的にはぜひ導入したい)
36
どうやって入力するか
38. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
入力はExcelにしました
表データ作成ツールとして必要十分である
使い慣れている開発者が多い
Google Spread Sheetと比べると一長一短
どちらも事例はあるので、最終的には好み
37
その結果…
39. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
マスタデータの種類ごとにブックを分割
A1セルをテーブル名と解釈し、複数のシートを結合して出力
シート名は関係なし
38
複数人での並行作業をどうするか
"id","name","type"
"1001","経験値アップ","EXP"
"2001","イベントアイテム","EVENT_ITEM"
item.xlsm
item_event2020.xlsm
item.csv
55. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
マスタデータ開放日時を自動登録
version master_tag start_at
1 tag#20200904_update 2020/09/04 18:00:00
version id name type value
1 1001 経験値アップ1 1 100
mst_item
data_version
master_tag: tag#20200904_update
start_at: 2020/09/04 18:00:00
"id","name","type“,”value”
"1001","経験値アップ1","EXP","100"
反映ツール
登録
▲開放日時
▲versionは自動採番
▼tag#20200904_update
54
56. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
何回分でも登録可能
version master_tag start_at
1 tag#20200904_update 2020/09/04 18:00:00
2 tag#20200911_update 2020/09/11 18:00:00
version id name type value
1 1001 経験値アップ1 1 100
2 1001 経験値アップ1 1 100
2 1002 経験値アップ2 1 200
mst_item
data_version
反映ツール
登録
"id","name","type“,”value”
"1001","経験値アップ1","EXP","100"
“1002","経験値アップ2","EXP","200"
▼tag#20200911_update
master_tag: tag#20200911_update
start_at: 2020/09/11 18:00:00
▲開放日時
▲versionは自動採番
55
57. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
クライアントアプリがマスタデータを「ダウンロード」して「展開」する時間を短縮したい
56
差分ダウンロード(開発中)
version update_type id name type value
1 UPDATE 1001 経験値アップ1 1 100
1 UPDATE 1002 経験値アップ2 1 200
1 UPDATE 1003 経験値アップ3 1 300
mst_item
反映ツールが直前のversionと
比較して自動的に登録
NONE: 変更無し
UPDATE: 追加/変更
DELETE: 削除
"id","name","type“,”value”
"1001","経験値アップ1","EXP","100"
“1002","経験値アップ2","EXP","200“
“1003","経験値アップ3","EXP",“300"
"id","name","type“,”value”
"1001","経験値アップ1","EXP","100"
“1002","経験値アップ2","EXP","250“
mst_item.csv
mst_item.csv
反映ツール
反映ツール
version update_type id name type value
1 UPDATE 1001 経験値アップ1 1 100
1 UPDATE 1002 経験値アップ2 1 200
1 UPDATE 1003 経験値アップ3 1 300
2 NONE 1001 経験値アップ1 1 100
2 UPDATE 1002 経験値アップ2 1 250
2 DELETE 1003 経験値アップ3 1 300
58. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
クライアントアプリが持っているマスタデータのversionによって返却すべきレコードを判定
57
差分ダウンロード(開発中)
クライアントのversionが1なら
この2レコードのみを返却
version update_type id name type value
1 UPDATE 1001 経験値アップ1 1 100
1 UPDATE 1002 経験値アップ2 1 200
1 UPDATE 1003 経験値アップ3 1 300
2 NONE 1001 経験値アップ1 1 100
2 UPDATE 1002 経験値アップ2 1 250
2 DELETE 1003 経験値アップ3 1 300
mst_item
クライアントのversionが0なら
この2レコードを返却
(初回ダウンロード)
59. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
複数人が並行作業できる仕組みを整備
厳密なスキーマによって、入力データのばらつきをコンバータが吸収
グルアーによるマスタデータの自動生成
バリデータによる徹底したチェック
段階的にリリースできる仕組みを整備
マスタデータをタグで管理し、開放日時で自動的に切り替え
マスタデータ更新時間を短くするための差分ダウンロード
58
ここまでのまとめ
60. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
1. 使用技術
2. データベーススキーマ管理
3. マスタデータ管理
4. 開発サーバ管理
59
アジェンダ
61. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
開発環境のスケーラビリティを実現するために
開発規模を意識して
開発サーバを100セット作っても管理コストが増えないようにする
– 実際にそんなに作るかはさておき
更新頻度を意識して
複数のアップデートを並行開発しても管理コストが増えないようにする
よくあるモバイルゲームの開発フローを辿っていくと、
この実現が難しいことが多い
60
開発サーバ管理のポイント
62. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
開発初期はクライアントアプリのみのことが多い
プロジェクトの良し悪しを判断するにはクライアント側が重要なため
61
よくあるモバイルゲーム開発の流れ
プロトタイプ
アルファ
ベータ
QA
サービス開始クライアントアプリのみ
63. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
ある程度できてきたらサーバと繋ぎこむ
開発サーバ(dev01環境)の登場
会社によって呼び方は様々
62
よくあるモバイルゲーム開発の流れ
プロトタイプ
アルファ
ベータ
QA
サーバと繋ぎこみ
dev01
サービス開始
64. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
開発が進むと「通信周りの作り込みをしたい」などの要件が出てくる
dev01の邪魔をしないように、とりあえずdev02環境を追加
この時点では「dev02環境使います」という声掛けで、まだなんとかなる
そろそろ手軽にサーバ更新したくなってくる
CIツール(Jenkinsなど)の登場
63
よくあるモバイルゲーム開発の流れ
dev01 dev02
65. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
開発後半になると、いろいろな要件で開発サーバが増える
社内レビューがあるので一定期間更新しないようにしたい
アップデート分の開発を進めたい
マスタデータを変更しつつ、いろいろなパターンでテストしたい
64
よくあるモバイルゲーム開発の流れ
dev01 dev02 dev03 dev04 qa01
......
66. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
「どのサーバがどうなっているか」を管理したくなる
開発サーバWikiの登場
65
よくあるモバイルゲーム開発の流れ
環境名 ビルド 用途
dev01 xxxxxxxxxx 主に使う
dev02 xxxxxxxxxx 通信周りの検証用
dev03 xxxxxxxxxx 社内レビュー用
dev04 xxxxxxxxxx アップデート開発用
qa01 xxxxxxxxxx テスト用
67. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
しかし、実際の開発サーバとWikiがずれると悲惨
そこで、CIツールの設定を自動的にWikiに反映
これで概ね解決
こんな感じの運用は多いと思います
66
よくあるモバイルゲーム開発の流れ
68. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
CIツールのジョブが増えていきがちで、設定に手間がかかる
開発サーバが1セット増えるごとにCIツールのジョブが増えていったり
Jenkins職人の誕生
開発サーバの設定を変更できるのは基本的にエンジニアのみ
大規模開発では、いろいろな人から設定変更依頼がくる
例)「××サーバを〇〇アップデートの状態にしてください」など
コミュニケーションコストが増えがち
そこで......
67
改善したいこと
70. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved. 69
ワークフローを比較
CIツール
開発者用
Wiki
dev01
dev02
Before
dev03
設定反映
設定
閲覧
設定依頼
自動更新
手動更新
エンジニア
プランナー
QA
CIツール dev01
dev02
After
dev03
情報取得
更新/
情報取得
閲覧/
設定
自動更新
エンジニア
プランナー
QA
開発管理
画面
✔常にDBを正とするので情報の流れがわかりやすい
✔エンジニア以外の開発メンバーが設定を変更できる
手動更新
DB
71. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
単独更新
設定されているブランチでビルドされたイメージを一覧表示し、
どれをデプロイするか選択
一括更新
選択したブランチが設定されている開発サーバを一括更新
70
ゲームサーバの手動更新
72. Copyright 2020 DELiGHTWORKS Inc. All Rights Reserved.
単独更新
好きなマスタタグで好きな開発サーバを更新
一括更新
好きなマスタタグが設定されている開発サーバを一括更新
71
マスタデータの手動更新