38.5K Views
July 15, 22
スライド概要
Game Creators Conference 2016の講演で使用したスライドです。
『最新のゲームエンジン開発を支える技術』 - 是松 匡亮 / 齊藤 俊介
株式会社カプコンが誇るゲームエンジン「RE ENGINE」を開発している技術研究統括によるカプコン公式アカウントです。 これまでの技術カンファレンスなどで行った講演資料を公開しています。 【CAPCOM オープンカンファレンス プロフェッショナル RE:2023】 https://www.capcom-games.com/coc/2023/ 【CAPCOM オープンカンファレンス RE:2022】 https://www.capcom.co.jp/RE2022/ 【CAPCOM オープンカンファレンス RE:2019】 http://www.capcom.co.jp/RE2019/
ゲームエンジン開発を 支える技術 CIの使い方とWebサービスの提供 株式会社カプコン 是松 匡亮 / 齊藤 俊介
はじめに • 題材 • カプコンで開発を進めている 新しいゲームエンジンの開発環境 • 新しいゲームエンジンの資料 • 『いまどきのゲーム制作環境』- 市山裕介/是松匡亮 • https://cedil.cesa.or.jp/cedil_sessions/view/1303
第一部 CIの運用とWEBサービス
第一部 / アジェンダ • 導入 • CIの運用紹介 • 見てもらえるCIへ • Webサービスの提供
導入 CI(継続的インテグレーション)の 必要性
困っていたこと • 出社して仕事を始めようとしたらビルドエラー • ビルドは通るが起動しない • 起動するがバグでゲームが始まらない これらが当たり前のように発生
CI黎明期 • 深夜に自動ビルドをするbatを作成 • エラーの検出は1日1回 • 実行テストは行わない • PCは1台のみ • 実施前よりもビルドが通りやすくなった
CI黎明期 • 要求 • 日中も頻繁にビルドを行う • 全プラットフォームの全ビルド構成 • 実行テストを行う • テストに合格したものは配布する • ビルド履歴を確認できる • 自作をするには要求が多すぎる
CIツール • Jenkinsを採用 • https://jenkins-ci.org/ • 採用理由 • プラグインによる機能拡張が容易 • 日本語の情報が入手しやすい • SlideShare, Qiita, ブログ, ... • 当時やりたかったことが簡単にできた
CIの運用紹介 コミットから配布まで
コミット / 全体像 Developers Repository CI
コミット / リポジトリへの送信 Developers Repository CI
コミット / CIの起床 Developers Repository CI
コミット / 構成 • svnを採用 • post-commitスクリプトを利用することが可能 • gitの場合はpost-updateが適切 • post-commitスクリプトでJenkinsを起床 wget http://jenkins/job/BuildEngine/buildWithParameters?BRANCH_NAME=trunk • 現場で採用しているスクリプトは附録ページにあります
ビルド / 全体像 Repository CI Server Developers
ビルド / ビルドの実行 Repository CI Server Developers
ビルド / ビルドの実行 • リポジトリから指定されたブランチをビルド • 開発者と同じ.slnをビルド • 複数台のスレーブPCが並行してビルドを行う • 複数のプラットフォーム • x64, PlatformA, PlatformB, ... • プラットフォームごとにすべての構成 • Debug, DebugOpt, Profile, QA, Ship • タイトルの要請に応じたカスタム構成 • レンダリングモジュールの差し替え, 社外貸出, etc.
ビルド / 結果の取り扱い Repository CI Server Developers
ビルド / 結果の取り扱い / 成功時 Repository CI Server Developers
ビルド / 結果の取り扱い / 成功時 • ビルドしたバイナリをNAS上に配置 • バイナリのMD5とリビジョンをサーバーに登録 • バイナリのMD5 と リビジョンの相互参照が可能 • ‘dev’属性としてマーク • テストに移行
ビルド / 結果の取り扱い / 成功時 / 実装 • バイナリのコピーはrobocopy • バイナリのファイルパスや属性は phpで受け口を作り、情報をMongoDBに格納 • phpへの送信はC#のコマンドラインツールを実装 • System.Web.WebClientクラスで10行程度
ビルド / 結果の取り扱い / 失敗時 Repository CI Server Developers
ビルド / 結果の取り扱い / 失敗時 • 開発者にエラーを通知 • メールによる通知は廃止 • リアルタイム性を重視 • チャットに流す • Skype for Business, IRC, Slack, ...
ビルド / 結果の取り扱い / 失敗時 / 実装 • エラー監視プロセスをJenkinsのジョブに登録 • 業務時間の開始から終了までの間、毎日実行 • 情報取得はJenkins Remote access APIを利用 • チャットツールへの通知は Lync APIを利用 CI Watch dog Developers
テスト / 全体像 Server CI Server Developers
テスト / テストの実行 Server CI Server Developers
テスト / テストの実行 • 事前に定義されている動作テストを実行 • 起動, ゲームの実行, メモリリークテスト • スクリプトビルドの互換性テスト • API変更はObsolete属性による移行期間設置をルール化 • 内製テストスイート • エンジンの挙動を非侵入的にテスト • テスト結果はJUnit形式で出力
テスト / 結果の取り扱い Server CI Server Developers
テスト / 結果の取り扱い / 成功時 Server CI Server Developers
テスト / 結果の取り扱い / 成功時 • サーバー上の属性を格上げ • ‘dev’から’stable’へ • シンボルサーバーに登録 • .dmpのデバッグ時にローカルシンボルが不要になる • “symstore”で検索 • 配信開始
テスト / 結果の取り扱い / 失敗時 Server CI Server Developers
テスト / 結果の取り扱い / 失敗時 • 開発者にエラーを通知 • ビルド失敗時と同様
配布 / 全体像 Server Users
配布 • ‘ブランチ名+構成+属性’で管理 • ‘trunk__81f16f39_00000000_stable’ • ユーザーはクライアントツールを通じて取得 • 取得する構成はタイトルごとに定義される • 参考 • アップデートは1日あたり15回 • trunkへのコミットは20回
まとめ Repository Developers CI Server Users
見てもらえるCIへ 遭遇した問題と解決した方法
CI導入の先にあったもの • 現場の歓迎する声 • 手動のデプロイが不要に • 従来は動作テストとリリースが手動 • エンジンのビルドはエンジンチーム任せ • 従来はタイトル開発者が自席でエンジンをビルド • 新たな問題 • チャットに情報を流しても対処されるまでが長い
観察していてわかったこと • 「どこを見たらよいのかわからない」 • 普段のビルドツールとは見た目が違うので戸惑う • “Jenkins”というだけで身構えてしまう人もいる • Jenkinsのページは開いてくれている • 対処が遅いのではなく、失敗理由がわかりづらい • スレーブPCやビルドツールの問題も発生する • 「Jenkinsよくわからない」に拍車を掛けてしまった
出来上がったもの • Jenkins上の情報を まとめたページ • 構成ごとに 配布中バージョン ビルド中バージョン コミットログ を表示
出来上がったもの • Jenkins上の情報を まとめたページ • 構成ごとに 配布中バージョン ビルド中バージョン コミットログ を表示
出来上がったもの / ビルドエラー時 • エラーと警告を表示 • 異常だと一目でわかる • ログをパースして 関連する行のみを表示 • 誰にでも理解できる • Visual Studioと同じ
出来上がったもの / テストエラー時 • ビルドエラーと 見た目を統一 • よくあるテスト失敗の 場合は解決策も提示
出来上がったもの / CIエラー時 • CI側の問題は別枠扱い • 迷わずCI担当者を 呼んでもらえるように • CI担当者いなくても ビルドフローを リセット可能 • 時間のロスと引き換え
出来上がったもの / 実装 • Jenkins の Remote access API を活用 • ほとんどの情報をJSON形式で取得可能 • php で json_decode() するだけ • CIエラーか否かの判定はログのパースで行う • svnコミットログは php 内で参照 • Svn::log()
得られた効果 • 狙い通り • すぐにエラーを直してもらえるようになった • CI担当者としてのメリット • Jenkinsを明確に意識させる必要がなくなった • Jenkins側を複雑なジョブ構成をしても困らない • Jenkins上の様々なデータを集約可能 • ビルドフロー上は関連のないジョブの状態をまとめて表示
まとめ • Jenkinsの標準UIは万人受けしない • 慣れてもらうまでの時間が長い • シンプルなUIは受け入れられやすい • エラーを放置したい人はいない • できるだけ早くエラー内容を確認できる手段が重要
Webサービスの提供 欲しい情報へのアクセスを手軽に
Webサービスのススメ • Webサービス化は業務効率を高める • 人の問題 • Webブラウザを立ち上げることに抵抗がない人が多い • デジタルネイティブ世代 • デバイスの問題 • WebはデバイスやOSを選ばない • スマートフォン、タブレット端末、PC • ビルド状態の確認以外にも様々なページを運用
更新情報 / 動機 • 通知メールを後から探すのが大変 • 関係のないメールまで結果に含まれてしまう • 探す人の検索能力に依存する • 検索機能をエンジンチームから提供 • 不要な情報が入り込む余地が無い
更新情報 / Webページ
更新情報 / Webページ
更新情報 / 実装 • フォームからPOSTされた内容を メール送信した直後にMongoDBへ登録 • 表示と検索には DataTables を採用 • サーバーはMongoDBの格納データを全部返す • Webブラウザ内でフィルタリング • 5,000+件の更新内容でもストレスなく検索可能
更新情報 / 効果 • 概ね好評 • タイトル開発者に多く利用されている • チャットツールで引用されるようになった • 以前:「○○さんがメールを送信されていたような」 • 現在:「http://.../ で報告されていますよ」
更新情報 / 今後の課題 • SVNとの連携が薄い • 「このリビジョンについては告知がされていない」 という問題の検出ができない
クラッシュレポート / 動機 • クラッシュ時のメール通知を行っていた • 数十件のメールが毎日のように届く • 同じ箇所でクラッシュしたメールも大量に届く • 過去のクラッシュ情報の検索と追跡が困難 • 修正状況を確認することができない • きちんとデータベースで管理するべき
クラッシュレポート / Webページ
クラッシュレポート / Webページ
クラッシュレポート / Webページ
クラッシュレポート / Webページ
クラッシュレポート / 実装 • メールの代わりにサーバーへ情報をPOST • サーバーはMongoDBに書き込み • 同一案件があればマージ • スタックトレースを比較 • WebページはMongoDBの内容を表示 • 基本は更新情報のページと同じ • 修正状況の更新があれば報告者にメール通知 • 「調査を開始しました」、「修正されました」
クラッシュレポート / 効果 • 同一案件のマージは効果が絶大 • 開発者も修正する気になる • 再発案件の検出も可能に • 進捗の通知メールは利用者を安心させる • メール通知の時は送りっぱなしだった • クラッシュレポートを送信するモチベーションに
クラッシュレポート / 今後の課題 • 案件マージの限界 • 似ている案件をマージすることができない • スレッドごとスタックトレースは異なる • 異なるプラットフォームのマージが困難
その他 / 動機 • 世の中のサービスは便利なものが多い • SlideShare, wandbox, Shadertoy, ... • 社内からアップロードはできない • 社内にも欲しい • 開発中エンジンの機能紹介もスライドでやりたい • 異なるコンパイラで挙動を確認したい • シェーダーも書きたい
その他 / Webページ
その他 / Webページ
その他 / Webページ
その他 / 効果 • 思っていたよりも多くの利用者が訪問 • UIに不自由があっても使ってもらえる • アウトプットの場を求めている人が多かった • 情報のアウトプットに抵抗感のない人が多い • スマートデバイスとSNSが浸透したことのメリット • 純粋に研究を行いたい人にも好評
第一部のまとめ • CIを導入することで手動作業を廃止 • 安定した環境を利用者に提供 • 見てもらえるCIは専用のWebページから • Jenkinsの情報を開発者フレンドリーな形へ • 社内Webサービスでやりたいことを形にする • 開発者のアウトプットしたい気持ちを無駄にしない
第二部 エンジン採用タイトルを サポートするCI
アジェンダ 1.複数構成のデプロイ 2.エンジンに依存するツールの自動更新 3.CIマシンでのダンプ解析 4.自動プロファイル 5.エンジン開発者と利用者のビルドエラーフロー
CIの運用紹介 複数構成のデプロイ
基本のCIビルドパイプラインのおさらい CI Build Test エンジン開発者 トランクにコミット エンジン利用者 エンジン配布
複数構成の必要性 エンジン利用者A 全部の機能が入った マスターのエンジンが 欲しい CI Build Test エンジン利用者B XXXミドルウェアは いらないから 除外して欲しい エンジン利用者C セキュリティの都合で ネットワーク系の機能を 全て除外して欲しい
ブランチでの提供 エンジン利用者A 全部の機能が入った マスターのエンジンが 欲しい トランク コミット エンジン開発者 エンジン利用者B CI 各ブランチ コミット Build Test XXXミドルウェアは いらないから 除外して欲しい エンジン利用者C セキュリティの都合で ネットワーク系の機能を 全て除外して欲しい
CIでの提供 エンジン利用者A 全部の機能が入った マスターのエンジンが 欲しい トランク コミット エンジン利用者B CI エンジン開発者 Build Test XXXミドルウェアは いらないから 除外して欲しい エンジン利用者C 各構成用の変更を加え、 各構成の数だけ エンジンを生成 セキュリティの都合で ネットワーク系の機能を 全て除外して欲しい
複数構成デプロイの主な処理 1. 必要な構成設定を作成 2. コミット時に構成の数だけCIのジョブを発行 3. 各CIジョブの最初でワークスペースのデータに対 して構成設定の適応 4. 各CIジョブは各構成のエンジンをデプロイ
構成の切り分け方針 • 基本はマクロでの各機能のON・OFF • .h .csproj .batなどのファイルを自動生成 • ソリューションから不要な設定の削除 • .sln .csprojから該当のビルド設定・参照設定を排除
構成設定の作成ツール
CIジョブの発行 構成の数だけ 下流ジョブを生成 Build Job A トランク コミット Start Job CI エンジン開発者 Build Test Build Job B Build Job C
デプロイまでのフロー CI Build Job A Test Job A エンジン利用者 Build Test 取得した構成を元に ソースコードの自動生成 設定ファイルから不要な構成の削除 各ユーザーが望む構成で エンジンを配布
CIの運用紹介 エンジンに依存する ツールの自動更新
エンジンに依存するツール エンジンコードを 参照している 依存関係にある エンジン ツール
ツールの自動更新 ツール 依存しているコードが 更新されたら 自動的にツールをビルドして コミット CI エンジン開発者 トランクにコミット
CIの運用紹介 CIマシンでのダンプ解析
クラッシュ時のフロー クラッシュ エンジン スタックトレースなどから クラッシュの概要を作成し サーバーに送信 上記の処理に必要なDLL等が存 在しない環境でエンジンが使用 されることがある エンジン開発者
CIでのダンプ解析 クラッシュ エンジン エンジン開発者 サーバーにダンプファイルを アップロード CI上でダンプファイルを解析して 結果をJson形式で返す CI
CIの運用紹介 自動プロファイル
多様なエンジン構成 プラットフォームA プラットフォームB Debug Release マスターエンジン シーン A シーン B シーン C XXXミドルウェアなし エンジン ネットワークなし エンジン Master プラットフォームC
早期発見したい問題 特定の構成・特定のシーンの 処理速度がいつの間にか低下している ・CIによる自動的なプロファイル
自動プロファイルのフロー CI エンジン 内製プロファイラでの プロファイル プロファイルの結果を ファイルサーバーと MongoDBに保存
CIの運用紹介 エンジン開発者と利用者の ビルドエラーフロー
エンジン開発者のビルドエラーフロー トランクにコミット ビルド エラー CI エンジン開発者 失敗を通知 トランクはエラー状態 修正されるまで ビルドは通らず エンジンも配布されない
エンジン開発者と利用者のデータ更新関係 エンジン開発者 エンジン利用者 ビルドが通らない環境を 配布されても困る CI エンジンプログラマ タイトルプログラマ 正常なCIビルドフローを おこなったリビジョンのみ配布 エラーが出たら解決されるまで 全てのデータ更新が止まる アーティスト ここのデータ更新は いつでも素早く行いたい CIで更新を止めるのは イテレーション速度の低下 につながる
エンジン利用者のビルドエラーフロー トランクにコミット ビルド エラー CI エンジン利用者 失敗を通知 コミットそのものが 取り消される トランクは常に コンパイルが通る状態 テスト等の厳密な 動作チェックはせず イテレーション速度を重視
第二部のまとめ ・複数構成のデプロイ マクロ定義での切り分けで自動化対応 ・利用者の更新をロックしないビルドエラーフロー
LICENSE • Microsoft Cloud and Enterprise Symbol Set Version 2.3 • https://www.microsoft.com/en-us/download/details.aspx?id=41937 • https://azure.microsoft.com/en-us/documentation/articles/architecture-overview/ • Jenkins Logo Artworks • Jenkins project (http://jenkins-ci.org/)
本編で解説しきれなかったこと 附録
post-commit スクリプト(CentOS 6.3で運用) REPOS="$1" REV="$2" # ----------------------------------------# BRANCH NAME EXTRACTION. # ----------------------------------------LOOKDIRS=`svnlook dirs-changed -r $REV $REPOS` LOOKFILES=`svnlook changed -r $REV $REPOS` MESSAGE=$(svnlook log $REPOS -r $REV) IFS=/ ary=($LOOKDIRS) if [[ $LOOKDIRS == trunk* ]] then branchName=${ary[0]} elif [[ ( $LOOKDIRS == branches/releases* ) ]] then ary2=($LOOKDIRSFILES) branchName=branches%2freleases%2f${ary2[2]} Fi # -----------------------------------------# CANCEL BUILD TRIGGER IF MESSAGE SAYS SO. # -----------------------------------------if [[ ( $MESSAGE == *¥[ignore¥]* ) ]] then branchName="" elif [[ ( $MESSAGE == *¥[docs¥]* ) ]] then branchName="" fi # -----------------------------------------# INVOKE JENKINS. # -----------------------------------------if [[ -n "$branchName" ]] # NOP then wget -O /dev/null http://jenkins.yours.com/job/BuildEngine/build?token=startBuild¥&BRANCH_NAME=$branchName Fi