SlideShare a Scribd company logo
新入社員のための大規模ゲーム開発入門
サーバサイド編
株式会社インフィニットループ
佐々木 亨基
2014/06/14 OSC Hokkaido 2014
自己紹介
・佐々木 亨基 ( ささき としき )
・ゆきこ yukicon
・ Twitter:@yukiconEx
・株式会社インフィニットループ所属
・制御系から Web 業界に転向
・学生時代の夢は理科の先生
・ゲームがつくりたくてプログラマに
・一旦は諦め一般のプログラマに
・��の後夢が叶って今はゲーム開発
・超適当
・のんびりゆったりまいぺーす
インフィニットループについて
・北海道札幌市にあるシステム開発会社
 約 100 名(契約スタッフ・アルバイト含む)で活動中
 社長も含め、ほぼ全員がエンジニア
・主な開発実績(主にサーバサイドを担当)
 ブラウザ三国志 (2009)
 戦国 IXA(2010)
 英雄クエスト (2010)
  Lord of Knights(2012)
 フォトバトラー (2012)
  Vim 検定 (2012)
  PHP 検定 (2013)
 ソードオブナイツ (2014)
新作ゲーム「勇者と 1000 の魔王」
iPhone AppStore で好評配信中!
こういうゲームをつくるお話です
インフィニットループについて
ゲーム開発って…
難しそう
どんな事してるかわからなくて怖い
自分なんかでは無理
新卒はもちろん
Web 系の業務経験がある人でもそう考えがち
実際は知らないだけ
そんなに怖いものじゃない!
幽霊の正体見たり枯れ尾花
はじめに
ゲームはどんな風に動いているのか
ゲーム開発とはどんなものなのかを知る
開発については具体的な手法やノウハウではなく
心構えや概念的な話がメイン
今日のお話
■ ゲームってどんな風に出来てるの?
■ 開発の流れ
■ 安定運用のための心構え
お題目
ゲームってどんな風に出来てるの?
一般的な Web サービス開発案件と同じ
LAMP 構成
Linux
Apache
MySQL
PHP 、 Perl 、 Python
言語は PHP 、 Perl 、 Ruby など様々
やってる事はなんであっても変わらない
ゲームってどんな風に出来てるの?
アプリの仕組みによって
Web サーバから返すレスポンスの種類が違う
・ HTML 型
一般的なサイトと同じく HTML を返す
ブラ三や Mobage 、 GREE の携帯ゲーム
・ API 型
HTML ではなく JSON を返す
Flash 、 Ajax 、スマホのネイティブアプリ
などのクライアントが存在
今はこちらが主流
ゲームってどんな風に出来てるの?
API が返す JSON とは
[{"name":"Pz.Kpfw. V Pantherr","gun":"7,5 cm KwK 42
L/70","weight":"44.8t","speed":"55","armor":"80","type":"MIDDLE
_TANK"},{"name":"Jagdpanther","gun":"8,8 cm PaK 36
L/56","weight":"45.5t","speed":"55","armor":"80","type":"TANK_D
ESTROYER"},{"name":".Kpfw. VI Tiger","gun":"8,8 cm PaK 36
L/56","weight":"57t","speed":"40","armor":"100","type":"HEAVY_T
ANK"},{"name":"Pz.Kpfw. Tiger II","gun":"8,8 cm KwK 43
L/71","weight":"69.8t","speed":"38","armor":"180","type":"HEAVY
_TANK"},{"name":"Jagdtiger","gun":"12,8 cm PaK 44
L/55","weight":"75t","speed":"38","armor":"250","type":"TANK_D
ESTROYER"}]
ゲームってどんな風に出来てるの?
API 型のゲーム
ゲームってどんな風に出来てるの?
Web
http://example.jp/userInfo?user_id=1000
サーバサイドの担当はここ
JSON
クライアントサイド
Flash 、 Ajax 、スマホのネイティブアプリ
Flash ゲームの通信を firebug で覗いてみると
API と通信してるのが良くわかる
ゲームってどんな風に出来てるの?
リロードせず API と何度も通信
レスポンスは JSON 文字列
開発の流れ
ある日新入社員が入ってきました
彼はメガネをかけていたので
あだ名はメガネになりました
名前 : メガネ
PHP+MySQL を少し触れる程度
個人での開発しかやった事がなく
チーム開発は初めて
開発の流れ
メガネ君はサービス開始からもうすぐ 1 年経つ
プロジェクト X に配属される事になりました
開発の流れ
プロジェクト X
サービス開始から 1 年
開発の準備
開発サーバのアカウントをもらい
開発サーバに ssh でログイン
開発の準備
開発
ログイン
開発サーバは共用なので他の人も使っている
開発の準備
開発
個人ごとに VM を立てているプロジェクトもある
開発の準備
VM VM
VM VM
その場合は VM のイメージをもらい
手元で起動して開発を行う
VirtualBox + Vagrant などを使用
開発の準備
VM
ソースはバージョン管理システムで中央管理
中央レポジトリからソースを落とす
svn 、または git を使用
開発の準備
レポジトリ
svn なら
svn checkout
git なら
git clone
変更したら中央レポジトリを更新
開発の準備
レポジトリ
svn なら
svn commit
git なら
git push
エディタはなんでも良いと言われましたが
ねこび~んが可愛いので NetBeans にしました
開発の準備
ソースを触れる、動かせる状態になったため
開発に加わる事が出来るようになりましたが
メガネ君に開発のイメージを持ってもらうために
開発体制と API の開発について説明します
開発体制
プロジェクト X は大きめのプロジェクトなので
結構��人数が関わっています
・プロジェクトマネージャー
・企画
・運用
・デザイナー
・クライアント開発
・サーバ開発
・インフラ担当
・テスト (QA)
開発体制
・プロジェクトマネージャー
意思決定
タスク管理
その他チーム運用が円滑になるように雑用
・企画
ゲームの企画立案、仕様策定
・運用
所謂運営チーム
お問い合わせ対応
動向調査
開発体制
・デザイナー
画面デザイン
エフェクト作成
・クライアント開発
クライアントサイド実装
ユーザの目に触れる部分
・サーバ開発
サーバサイド実装
目に見えない裏方
開発体制
メガネ君はここ
・インフラ担当
サーバ構築
リソース監視
・テスト (QA)
ゲームのテスト、デバッグ
Quality assurance( 品質保証 )
開発体制
チームで開発を行い
チームで運用をやっている
企画は絶対のような明確な上下関係はない
役割分担はあるが相互理解が大事
例えば
開発→企画
「この計算式バランス悪くないですか?」
言われたまま実装するだけでなく
ブラッシュアップの手助けとなるので遠慮なく意見を言う
運用→インフラ
「イベントやるのでサーバ増強お願いします」
イベントはアクティブ率が上がるというチームとしての共通認識
開発体制
ゲームへの理解は業務知識
最低限全機能を知るくらいにはプレイをする
本気過ぎてトッププレイヤーになるメンバーも
当然本番でチートはご法度なので
みんな普通にガチプレイ
開発体制
API の開発
API の開発
仕様書
企画
サーバ開発
クライアント開発
開発
企画から仕様が来る
ユーザの情報を表示する画面の仕様です
API の開発
サーバ開発 クライアント開発
■ パラメータ
・ユーザ ID
■ レスポンス
・ユーザ名
・レベル
相談して API の仕様を決める
こんな感じでいきましょう いきましょう
サーバ主導で決めるかクライアント主導で決めるかは
プロジェクトによって異なる
API を実装
API の開発
// ユーザ情報取得
$user_info = getUserInfo($_GET['user_id']);
// 必要な情報を配列に入れる
$response = array(
'name' => $user_info['name'],
'level' => $user_info['level'],
);
// JSON で返す
echo json_encode($response);
でけた
手元で動作確認
API の開発
動いてる気がする
API の開発
サーバ開発 クライアント開発
クライアント
実装の済んだ最新のクライアントを受け取る
どうもです 最新版です
Flash なら開発サーバに設置
スマホアプリなら開発端末にインストール
API の開発
つなぎ込みの確認
動いてる気が しますね
yukicon
レベル :27
開発に加わるようになったメガネ君
担当した機能のテストもすんなり終わり
遂に本番にアップされる時が来ました
アップデート
プロジェクトによっても異なるが
本番環境に至るまでの環境は 4 つほど
・開発環境
・テスト環境
・ステージング環境
・本番環境
アップデート
アップデート
開発
テスト
ステージング
本番
ここで開発
最新ソース、最新データで動作する環境
開発者各個人が手元のソースで実行
最新ソースで Fix 前のマスタデータの確認
開発中のため動作が不安定なのは当然
アップデート
ここでテスト
ある程度安定版のソースで動作する環境
テスト部隊が操作してデバッグを行う
アップされた直後では
動作はするがバグがある状態
開発
テスト
ステージング
本番
アップデート
ここでも確認
テストが通った安定版のソースで動作する
本番にかなり近い環境
これ以降ソースの変更は無く
そのため本番と同じソースで稼働している
本番で不具合があった場合の再現確認もここ
開発
テスト
ステージング
本番
アップデート
最後に
ユーザがプレイする環境
開発
テスト
ステージング
本番
メンテナンスについて
・定期メンテナンス
アップデートのため毎週か毎月に一回などゲームを止め
定期的に行われる予定されたメンテナンス
・緊急メンテナンス
今しなければいけないが止める必要がある更新をする場合や
発生した不具合による被害が広がらないようにする場合など
止めた方が良い場合には止めてしまう
重要なインフラではなくゲームなので、ある意味では止めても良い
アップデートが頻繁な事から
どうしても予期せぬ不具合が発生する確率が上がるのも事実
・無停止メンテナンス
ゲームを止めずに動かしたままアップデートする事
裏当てなど呼び名は様々
アップデート
予定されているのは定期メンテナンスのみ
アップデート
定期メンテ 定期メンテ 定期メンテ
定期メンテナンス後に不具合が見つかったため
無停止メンテで対応
アップデート
定期メンテ 定期メンテ 定期メンテ
無停止メンテ
済
もひとつおまけに対応
細かい事なら定期メンテナンスに回す事もある
アップデート
定期メンテ 定期メンテ 定期メンテ
無停止メンテ
無停止メンテ
済
データが異常となったユーザが居る事が判明
対象ユーザが増え続けているため
緊急メンテナンスを開始
アップデート
定期メンテ 定期メンテ 定期メンテ
無停止メンテ
無停止メンテ
済済
緊急メンテ
後日無停止メンテにより補填対応
アップデート
定期メンテ 定期メンテ 定期メンテ
無停止メンテ
無停止メンテ
済済
緊急メンテ
無停止メンテ
いざ本番となるとやはりいろいろと起こり
アップデートの大変さを知ったメガネ君
しかし同時に刺激的でもあり
安定運用のために頑張ろうと決意するのであった
安定運用のための心構え
ゲームはリリースしてからの運用が長い!
ブラウザ三国志
2009 年 7 月 15 日正式サービス開始
もう少しで 5 周年
安定運用のための心構え
リリースして終わりではない
ではリリース後にどんな事が起こるのか?
人間は痛みで覚える生き物
良くある失敗から失敗しないための心構えを学ぶ
運用失敗あるある
良くある失敗その 1
運用失敗あるある
データ不整合
運用失敗あるある
?
=
ある日、メガネの所属するプロジェクト X に
ユーザから問い合わせが
データ不整合
データ不整合
HP 500/1000
攻撃ログ
A の攻撃 300 ダメージ
B の攻撃 600 ダメージ
C の攻撃 500 ダメージ
ボスが死んでない!
データ不整合
HP 500/1000
攻撃ログ
A の攻撃 300 ダメージ
B の攻撃 600 ダメージ
C の攻撃 500 ダメージ
これだけが有効になっている
データ不整合
メガネの実装が悪い!
・同時処理が多く行われる
人気のあるボスに多くのユーザが殺到
同じユーザを 2 人が同時に攻撃など
→ テスト時は発見が困難なデータ不整合が発生
設計の段階からエンジニアが意識する必要がある
データ不整合
・データ不整合を防ぐためしっかりとロックする
1 人がボスを叩いている間はボスの情報を行ロック
SELECT * FROM t WHERE id = 1000 FOR UPDATE
データ不整合
データ
A
B
他の人使っちゃダメ
B は A のロック解放を待つデータをロック
・ロック範囲に気をつける
ロック範囲が広すぎると並列処理性能に影響が出る
ロック範囲は最低限にしておくべき
MySQL の場合はインデックスを使ってロックする
インデックスが効かないと事実上のテーブルロックになる
・デッドロックに気をつける
データ不整合を恐れてロックを増やしすぎると起こりがち
ロックするテーブルの順番を統一するなどして対策する
ただしどんなに注意しても起こる時は起こる
その場合はループしてやり直すように実装する
データ不整合
良くある失敗その 2
運用失敗あるある
負荷が高まる
運用失敗あるある
!
ある日のメンテナンス後
明らかに普段よりも DB サーバの負荷が高くなり
レスポンス速度が悪化
負荷が高まる
どうやらこんなシンプルなクエリが問題らしい
負荷が高まる
SELECT * FROM t WHERE c2 = 'XXX';
SELECT * FROM t WHERE c2 = 'YYY';
SELECT * FROM t WHERE c2 = 'ZZZ';
どうやらこんなシンプルなクエリが問題らしい
負荷が高まる
SELECT * FROM t WHERE c2 = 'XXX';
SELECT * FROM t WHERE c2 = 'YYY';
SELECT * FROM t WHERE c2 = 'ZZZ';
よく見るとインデックスが使われていない!
このままでは夜のピークタイムは越えられない
インデックスをつけるため緊急メンテへ
※MySQL5.6 からは動かしながらインデックスが追加できるようになりました
負荷が高まる
メガネがインデックスをつ��り忘れた!
・ユーザは負荷に敏感
一般的な Web サイトと比べ、ユーザの操作量は段違いに多い
一般的な Web サイトで許される程度の”ちょっと重いな”が
毎日の操作で積み重なるとイライラ
いつもと比べて重いとイライラ
→ ユーザ離脱
レスポンスが遅いとゲームは成り立たない!
負荷が高まる
・インデックスを意識する
レコード数が多いテーブルでは
インデックスの効かないクエリは極端な負荷になる
CREATE TABLE t (
id int(11) AUTO_INCREMENT,
c1 varchar(10),
c2 varchar(10),
PRIMARY KEY (id),
KEY c1 (c1)
)
主キー
SELECT * FROM t WHERE id = 1000;
インデックスがついている
SELECT * FROM t WHERE c1 = 'AAA';
インデックスがついていない
SELECT * FROM t WHERE c2 = 'BBB';
負荷が高まる
×
○
○
・無駄な処理はしない
特に DB アクセスはデリケート
何度も同じクエリを発行したり
ループ内で何度もクエリを発行したりしない
×
SELECT * FROM t WHERE id = 1;
SELECT * FROM t WHERE id = 2;
SELECT * FROM t WHERE id = 3;
SELECT * FROM t WHERE id = 4;
○
SELECT * FROM t WHERE id IN (1, 2, 3, 4);
負荷が高まる
良くある失敗その 3
運用失敗あるある
データベースの肥大化
運用失敗あるある
ある日、突然レスポンス速度が悪化
前回のメンテナンスからは結構日にちが経っており
直前に原因となりそうなアップデートもない
データベースの肥大化
起こるタイミングは不定
ただどうやら
DB サーバのディスク I/O がネックになっている
データベースの肥大化
起こるタイミングは不定
ただどうやら
DB サーバのディスク I/O がネックになっている
調査を進めると
DB 容量の増大により
メモリ内で処理しきれなくなったため
ディスクアクセスが多発しているのが原因だった
データベースの肥大化
データベースの肥大化
なんかもう全部メガネが悪い!
※ 初期設計が悪いのでメガネは悪くありません
・サービス運用を続ければユーザは増え続ける
当然データも増え続ける
ユーザ数が多ければ多いほどデータ増加は激しい
・インデックスがメモリに乗らなくなると突然重くなる
順調に捌けているように見えても
ある日突然重くなるという事が起こる
データベースの肥大化
・設計段階から破綻しないように考えておく
際限なしに溜まり続けるデータが無いようにする
メールは最新 50 件のみ保存
行動ログ情報の有効期限は 1 ヶ月
テーブルパーティショニングの検討
水平分割 (Sharding) の検討
まずそうならこうするという対策を必ず考えておき詰まないように
・定期的に監視をする
最もレコード数が多いテーブルは何レコードくらいか
最も容量の大きなテーブルは何 GB くらいか
現在の DB 容量とメモリの関係はどれくらいか
データベースの肥大化
良くある失敗その 4
運用失敗あるある
コードが難解
運用失敗あるある
function isError($id)
{
:
:
:
return array($data1, $data2);
}
!?
・ゲームとは長く付き合う事になる
開発期間よりもサービス期間の方が長い
また、リリース後も頻繁にアップデートが行われる
→ 設計ミスなどの技術的負債はプロジェクトを苦しめ続ける
小さな事でも長く長く効いてくるので結果的には大問題
・開発はチームで行っている
好き勝手に書くと場所ごとに別物になってしまい混乱を招く
自分以外が改修する事も多い
→ 属人化した読めないコードでは成り立たない
動けば良いやではダメ!
コードが難解
・可読性、保守性の意識を
プログラミングの基本ではあるが案件的に重要度が高い
コーディング規約の遵守
特別な理由が無ければトリッキーな実装は避ける
他人が読んでも理解出来るかどうかを考える
1 年後の自分は他人なので、 1 年後に見てもわかるように
・レビューしてもらう
最初は誰でもわからないのが当然
こんな実装にしてみたいと思うんですけどの設計段階から
実際に書いたコードまで
チームの先輩にレビューしてもらい学んでいく
レビューには自分の考えをしっかり持って望むこと
コードが難解
・恐れずにリファクタリングする
技術的負債は返済しなければ溜まる一方
触るのが怖いかもしれないが放っておくともっと面倒な事になる
つらいなと感じる事があったら放置せず修正する癖をつける
他の場所に同じようなコードがあるなら合わせて修正する
方針について心配なら先輩に相談すると吉
・こだわり過ぎるのもいけない
理想を追い求めすぎてもままならない
チーム内に思想の違う人が居たり、ついてこれない人が居たり
必要以上に工数がかかってしまったり
自分としては正しくなくても、チームとして正しいなら受け入れよう
郷に入っては郷に従え
理想と現実の狭間で上手く生きる
コードが難解
今挙げた 4 つの問題に共通する事は
全てエンジニアの設計・実装が悪くて起こる
という事
日々の心構え、意識によってのみ防ぐ事ができる
今動いているから良いのではなく
後々こんな問題が起こるのでは?
という意識が大事なのだと学んだメガネ君でした
運用失敗あるある
これで一人前!
ゲーム開発といってもそんなに特殊な事はない
ただし
・開発をチームで行っている
・アップデートを繰り返し長期運用する
この 2 点については意識しておく必要がある
そして何よりも面白い
ユーザの反応がダイレクト���見える、届く
関わったゲームにプレイヤーとして参加する喜び
他の案件では得難い体験
最後に
インフィニットループでは、エンジニアを募集しています
・社長も含めほぼ全員がプログラマで技術者に優しい環境
・勤務地は北海道札幌市、他社出向などは無し
・おいしい食べ物、自然いっぱい、花粉少ない、涼しい
・短い通勤時間、徒歩や自転車で通勤が可能
・ U ターン、 I ターン大歓迎
・ PHP 開発エンジニア
・スマホ開発エンジニア
・ MySQL エンジニア
・インフラエンジニア
求人募集
ご清聴ありがとうございました

More Related Content

新入社員のための大規模ゲーム開発入門 サーバサイド編