【Unite Tokyo 2019】運用中超大規模タイトルにおけるUnityアップデート課題の解決手法と事例

3.6K Views

September 26, 19

スライド概要

2019/9/25-6に開催されたUnite Tokyo 2019の講演スライドです。
秋友 覚(株式会社コロプラ)
山本 康平(株式会社コロプラ)
松浦 章人(株式会社コロプラ)

こんな人におすすめ
・短期~中期(リリース1~2年目)運用タイトルに携わる開発者
・リリース前タイトルの開発に携わるエンジニア
・ビルドパイプラインを構築しているエンジニア

受講者が得られる知見
・移行に伴った必要作業の見積もりの一端
・大量ファイルのビルド環境構築の手法
・運用を長期化できた場合に準備すべきこと

Unityのイベント資料はこちらから:
https://www.slideshare.net/UnityTechnologiesJapan/clipboards

profile-image

リアルタイム3Dコンテンツを制作・運用するための世界的にリードするプラットフォームである「Unity」の日本国内における販売、サポート、コミュニティ活動、研究開発、教育支援を行っています。ゲーム開発者からアーティスト、建築家、自動車デザイナー、映画製作者など、さまざまなクリエイターがUnityを使い想像力を発揮しています。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

運用中超大規模タイトルにおける Unityアップデート課題の解決手法と事例 ~将来アップデートするために~ 株式会社コロプラ 秋友覚 山本康平 松浦章人

2.

自己紹介 *秋友 覚* 全社横断的な技術サポートを行う部の部長 1. コンソールゲーム、モバイルアプリ開発を経験 2. 2014年コロプラ入社 3. 『クイズRPG 魔法使いと黒猫のウィズ』や 『白猫テニス』などの開発、運用を経験 2

3.

講演概要 ❏ アップデートプロジェクト全体像 ❏ アップデート時に発生した問題事例 ❏ アップデートを支えた技術 3

4.

アップデートプロジェクト 全体像 4

5.

アップデート理由 ❏ ストア要件を満たさなくなった ❏ Google Play にて 64bit 対応が必須 ❏ 使用していた Unity バージョンでのサポートアナウンス無し ❏ 2019年8月以降、非対応はアプリ更新時の審査通過不可 ❏ その他 ❏ Unityの最新機能が使えない (JobSystem, Timeline … ) ❏ 社内共通ツール/フレームワークの導入が困難 5

6.

Unityアップデート理由 6

7.

アップデート対象 ❏ Unity4 から Unity2018.2 ❏ Unity2017 LTS でのサポートアナウンス以前に着手 ❏ Unity2018.2 から Target Architecture 「ARM64 」の Experimental が外れた ❏ Unity2018 LTS のリリース前に対応が必要だった ❏ 弊社内の超大規模な運用中タイトルすべて ❏ 運用6年 『クイズRPG 魔法使いと黒猫のウィズ』 ❏ 運用5年 『白猫プロジェクト』 本講演は上記2タイトルでの事例をご説明します 7

8.

アップデート対応体制 ❏ 専任の対応チームを結成 ❏ 理由 ❏ アップデートに関する情報の集約 ❏ 仕様や問題解決方法の共有が容易 ❏ サービス運用タスクによる影響が少ない 8

9.

アップデート対応体制 ❏ 専任の対応チームを結成 ❏ メンバー構成 ❏ ❏ ❏ ❏ 黒猫 : 1人 白猫 : 2人 共通で発生する問題対応 : 3人 全体の管理調整 : 1人 9

10.

アップデート対応体制 ❏ 期間 ❏ 黒猫 2018/6 ~ 2018/11 ❏ 白猫 2018/6 ~ 2019/2 10

11.

アップデート対応の課題 ❏ アップデートするアセットの量 ❏ Unity の仕様変更追従 ❏ サービス運用との連携 ❏ アプリ、アセットビルド環境の構築 11

12.

アセット数

13.

アセットに関わる数字 ❏ 白猫 ❏ プロジェクトサイズ ❏ 総ファイル数 ❏ 黒猫 ❏ プロジェクトサイズ ❏ 総ファイル数 約210GB 1,037,972ファイル 約107GB 397,615ファイル 13

14.

盛ってるでしょ? 14

15.

証拠のデバッグ進捗表 15

16.

キャラモデル 約2,400体

17.

キャラスキル 約2,800種 ※ さらに武器固有スキル約750種

18.

クエスト 約5,000 over ※ 復刻予定なしや、共通クエスト (プレゼント企画とか)を除く

19.

エフェクト 約17,000

20.

ボイス 約226,000

21.

iOS / Android 両端末 = x2 もちろんAndroidは、最低でも 各GPUアーキテクチャで確認

22.

これぞ 超大規模 22

23.

アセット数の影響 ❏ QA項目の増加 ❏ 個別対応作業の増加 ❏ インポート時間の増加 ❏ ビルド時間の増加 ❏ バージョン管理コストの増加 23

24.

アップデートプロジェクト再確認 ❏ ストア要件を満たすために ❏ 対応チームを結成して ❏ 8~9ヶ月くらいで ❏ 5~6年運用したタイトルの ❏ 数十万規模のアセットを ❏ なるべく楽な手法でがんばる 24

25.

必要なアップデート処理 25

26.

自己紹介 *山本 康平* 全社的な効率化ツール・ライブラリ開発者 1. 2. 3. 4. コンソールゲーム開発を経験 2014年コロプラ入社 タイトルのメインプログラマーを経験 『白猫プロジェクト』の運用を経験 26

27.

アップデート初期作業 ❏ Unity の自動更新かける ❏ 自動更新でコンパイルエラーが残った箇所を修正 ❏ ストアアセットのバージョンマクロなどに対応 ❏ Obsolete 指定関数もできれば修正 ❏ 不正なアセットを検出する ❏ Missing 存在しないアセットを参照しているアセット ❏ 正常動作しなくなったストアアセットを参照しているアセット 27

28.

アップデート初期作業 ❏ 実行して不正な挙動を確認、調査 ❏ 実行時の例外、エラー、警告 ❏ 必要なものが消えている ❏ メニューが遷移しない ❏ ゲーム内の要素をどれだけ知っているかが重要 ❏ アップデート処理をかける ❏ 自動化できそうなものはスクリプト用意する ❏ 自動化できなさそうなものは検出スクリプト用意する 28

29.

ストアアセットの更新 例:2Dスプライト、アニメーションアセットが使えない ❏ ❏ ❏ ❏ ❏ なぜなら アセットが生成する Atlas が生成されない なぜなら 内部で TextureType を指定している部分が通らない なぜなら 定数指定されていた TextureType がもうない そして そのアセットはもう更新されてない そして そのアセットは改変ライセンスが不明確でパッチ当てられない 対応:アセット同等の2Dライブラリを作る 教訓:サポート継続可能性はよく検討する 29

30.

不正スクリプト修正(一例) ❏ MonoBehaviour の new Unity の作法としてそもそも is not allowed. 対応スクリプト: new キーワードに続くシンボル名で GetAssemblies して IsSubclassOf(typeof(MonoBehaviour)) だったら検出 ❏ NameToLayer をクラス変数に代入 初歩的ミス、仕様勘違いは スクリプトでチェック 少し気付き難いが実行時エラーとなる AddComponent() 出来ない、のちに Null 参照などの原因となる “NameToLayer is not allowed to be called from a MonoBehaviour constructor” 対応スクリプト: NameToLayer() の論理行頭に private などの修飾子があれば検出 30

31.

不正アセット修正 ❏ 仕様変更の煽りを受けたシェーダー ❏ 仕様変更の煽りを受けたパーティクル ❏ アセットそのものをうっかり消した ❏ 他のアセット作るときに上書した ❏ 当たり判定不要なエフェクトに Collider がついている なるべくスクリプトで検出、修正する 31

32.

目でみる 不正アセット 32

33.

正常なアセット例 ほぼ Mobile Unlit なモデル 33

34.

不正アセット例 まっしろ Material は無事だが Texture アセットが無い 対応: Git の歴史を遡り、 元気だった頃の Texture を救出 34

35.

不正アセット例 ピンク Material が不正な状態 大体の原因は Shader エラー グラフィックプログラマは この色が大嫌い 対応: Particle などは Renderer の Material モデルの場合は対象 Shader コンパイルのログなどを調査、修正 35

36.

不正アセット例 ???? UVマッピングがぐちゃぐちゃ 目を凝らしてみないと気付かない 最悪のパターン 対応: 発生パターンの絞り込みは断念 Maya から再出力すると回復 異なる FBX エクスポーターを 使用されていたのか? 36

37.

Unityの仕様変更への対応 37

38.

シェーダーの仕様変更 ❏ Unity4 時代の TexGen は廃止 ❏ Unity4 時代の Fog は廃止 シェーダー自体は grep なりで探して修正 もしくは参照している Material を検索して 別シェーダーに置換 38

39.

スクリプト処理例 Unity4 系で Fog を利用していた Shader に対する処理 これをすべての Material に対して行う場合 39

40.

スクリプト処理にかかる時間 ❏ AssetDatabase に 55万個 ❏ うち t:Material が 15万個 ❏ 1 Material 処理に0.1秒 ❏ かかる時間は 15,000秒 = 4時間弱 ❏ こんな処理が 10 個程度 40

41.

こんなペースじゃ 修正おわらない 41

42.

処理を効率化した手法 ❏ スクリプト処理専用マシンを用意する ❏ 物量には物量で対抗する ❏ 絶対に修正作業と競合するのでタイミングは調整する ❏ なるべく yaml テキストとして編集する ❏ 全 Asset を Dirty にして SerializeVersion 上げる ❏ .meta, .prefab にほとんどの情報がある 例えば prefab なら ❏ 参照は GUID を grep する Component 要素の値=参照が ❏ なるべく AssetDatabase 使わない 42 4桁から8桁になる

43.

処理を実装する上で ❏ 処理によっては検出するだけにとどめる ❏ Missing が正しいことも稀によくある ❏ 検出されたリストを目視チェックでも十分では? ❏ 数個エラーがある程度なら人力でも十分では? 例:制作中のアセットがたまにまぎれこんでしまうエラー リストアップだけして作業者に確認してもらうのが楽&速い&堅実では? 43

44.

処理を実装する上で ❏ スクリプト処理にはかならず進捗表示と キャンセル機能を実装しておく ❏ 処理経過のログを less ❏ アセットを diff ❏ 想定外の差分などが出たら即座に停止 想定外の処理内容になったら早めに止めないと 時間が無駄になります 44

45.

ParticleSystemの仕様変更 パラメーターの意味が違う 左: Unity4 右: Unity2018.2 「Render Alignment」が「Render Alignment」「Simulation Space」に分離 もちろん変換などしてくれないので見た目が変化する 45

46.

対応手法例 Particle を元の状態に変換する処理を作成 master からマージしてエフェクトを取り込む毎に実行 46

47.

AudioClipのデフォルト値 「force to mono」が有効な AudioClip にノイズが出る。 Normalize がデフォルト有効になっているのが原因。 0 Normalize なし Normalize あり 47

48.

物理挙動仕様変更 Physics + CharacterController を使用 ❏ PhysX 2 ( Unity4 以前) ❏ PhysX 3 ( Unity5 以降) ❏ PhysX 3.4 ( Unity2018.3 ) ❏ PhysX 4.1 ( Unity2019.3 ) Unity 内部物理エンジン( PhysX )はバージョン毎に異なる Unity4 から アップデートで大きく挙動が変化した ※残念ながら Unity2018以降も挙動が変化する可能性があります 48

49.

あなたのPhysXはどれ? お使いの環境を思い出してください ❏ ❏ ❏ ❏ ❏ CharacterController 制御のモデルを操作 Collider 形状は Capsule モデルを右方向に移動させる 別のモデルに Collider つける 操作モデル方向に移動させる RigidBody がある / ない場合 どのような挙動になりますか? 49

50.

RigidbodyなしのCollider 50

51.

RigidbodyありのCollider ※ ちなみに Unity2018.3 以降だと押し出されます 51

52.

挙動変更への対応 ❏ 原因は CharacterController の OverlapRecovery ❏ めり込みからの回復を制御する機能 ❏ Unity4 にはなかった機能 この機能により移動オブジェクトにめり込んだ際の 挙動が変化 52

53.

挙動変更への対応 ❏ 対抗策は enableOverlapRecovery ❏ 押し出しが有効になるフラグがある ❏ 無効にしても Unity4 と同じ挙動にはならない ❏ しかも地面下への落下が多発する ❏ 地面への設置判定が Unity4 比較で厳格化した 挙動が変化する箇所の量、重要度を比較して enableOverlapRecovery は有効にしておくことに・・・ 53

54.

ParticleSystemのバグ (リリースノートより) ParticleSystem Particles: Particle System bounds no longer ignore Shape Y scale when using Rectangle emission shape. ❏ メインモジュールの 3D Start Size で変更された Y ( Z ) スケールが Bounds に反映されない ❏ Unity2018.3 で修正済み ❏ Unity2018.2 にはバックポートされなかった 54

55.

右から左にフレームインする演出 理想 現実 55

56.

対応策 エフェクトの Awake で Bounds を広げる ??? 56

57.

ParticleSystemの“バグ修正” Particle の SubEmitter がちゃんと機能する ❏ Unity4 では SubEmitter は出たり出なかった(バグ仕様) ❏ Unity2018 ではちゃんと出るようになった(バグ修正) ❏ Unity4 ではデザイナがエミット数を増やして対応 ❏ 出ないことがあるので若干多めに設定 ❏ バグ修正によってエミッション量が増加(正常化) バグ修正は大変ありがたいのですが... 57

58.

エディタ仕様変更例 細かな仕様変更 Depth 精度がシーンビューとプレビューで異なるため見た目も異なる https://github.com/UnityTechnologies/UnityCsReference/blob/master/Editor/Mono/Inspector/PreviewRenderUtility.cs#L29 58 6

59.

リリースまでの流れ 59

60.

リリースまでのイテレーション ❏ ゲーム内のイベント単位でマージ ❏ マージ時に競合したアセットをチェック ❏ prefab がマージできてても基本的に theirs をとる ※ちなみに施策ブランチマージした日は軽く 1000 コミットとびます ❏ 更新スクリプトの実行&対応 ❏ “Unity2018 のためにこう作ってくださいね”が浸透すれば不要になる ❏ 運用で追加要素をデバッグリストへ追加 ❏ 創意工夫に溢れたレベルデザインによる不具合は対応方法考える... 60

61.

リリーススケジュール 基本的にアセットに下位互換はないので、 どのアップデートから Unity2018 で作業するか決めておく 61

62.

今後の バージョンアップに 向けたご提案 62

63.

次のバージョンアップのために ❏ アセットは適宜バリデーションする ❏ アップデート時に気付いても手遅れです ❏ バージョン固有のものはリストアップしておく ❏ 例)バグを回避するためのコードやデータ ❏ アセットの参照経路を把握しておく ❏ 数値で参照されるアセットも追えるように ❏ 創意工夫はほどほどに ❏ 物事には適切な方法があります 63

64.

アップデートを 支えた技術 〜弊社の取り組み〜 64

65.

自己紹介 *松浦 章人* ビルド環境改善に取り組むビルドエンジニア 1. 2015年コロプラ入社 2. ゲームプログラマとして運用を経験 3. 全社的な開発環境の改善に着手 65

66.

アプリビルド 66

67.

バックエンドが 相当進化しました From いらすとや Unity4 Unity2018

68.

でも弊社では

69.

かなり少ない変更で 対応が可能でした

70.

アプリビルドの対応 ❏ ❏ ❏ ❏ Android のアーキテクチャ修正 Scripting Backend を Mono から IL2CPP に変更 NDK の設定追加 mainTemplate.gradle の追加 以上 70

71.

なぜ少ない変更で 対応が可能だったのか?

72.

弊社のビルドパイプライン方針 ❏ ビルドスクリプトは共通化 ❏ ビルドパイプラインは Unity4 ~ 最新 Unity まで対応 ❏ ❏ ❏ ❏ ❏ 移行完了したので現在は Unity2018.2 から最新まで 必要最低限の機能のみ実装 コードは全て Git で管理 アップデート時には設定変更のみで対応 Jenkins 構成も共通化 72

73.

スクリプト構成 ❏ 1) Jenkins Common Tools ❏ 2) App Build Tools ❏ 基本的にはこの2つをメインに機能追加する ❏ ライブラリを更新する方式で各プロジェクトがとりこむ ❏ 3) プロジェクト個別 Tools ❏ テンプレートを提供し、各プロジェクトが固有の処理を追加する ❏ 4) Jenkins Plugin ❏ 社内でアップデートセンターを作って配布する 73

74.

パッケージ構成 74

75.

Jenkins構成 ❏ GCP 上に master 構築 ❏ Mac マシンを slave 化 ❏ 統一ディレクトリ構成 ❏ アプリケーションパス命名規則 ❏ ワークスペース使用方法 75

76.

アプリビルドのフロー ❏ フローは全プロジェクトで共通 ❏ Unity ビルド → Xcode / Gradle ビルド ❏ Gradle ビルド不要のプロジェクトもあり ❏ サーバへのビルド成果物アップロード ❏ ビルド通知 76

77.

ビルドスクリプト ❏ Unity ビルド ❏ 複数バージョンあるがほとんど同じコード ❏ Xcode ビルド ❏ 今はバージョンによるスクリプトの違いは無い ❏ Gradle ❏ apk と aab による違いはあるが、ほとんど同じ 77

78.

Unity ビルドスクリプトの変化 Unity4 Unity2018 78

79.

追加・変更された機能の例 ❏ Application Identifier の設定方法が変更 ❏ Automatic Signing が追加 ❏ Scripting Backend の設定方法が変更 ❏ Android の IL2CPP が追加 ❏ Android のアーキテクチャ設定が変更 ❏ .Net 4.6 が追加 ❏ コマンドラインオプションが変更 など 79

80.

設定項目 エディタ スクリプト ❏ API Compatibility Lv ❏ Scripting Backend ❏ Scripting Define Symbols ❏ Application Identifier ❏ (Android)Target Architecture 他 他 80

81.

プロジェクト個別Tools 共通化してもプロジェクトの個別対応は必要 ❏ なるべく Unity の PreProcess や PostProcess で対応 ❏ なるべく個別対応を入れやすいように設計 ❏ 全く同じコードで全てのプロジェクトを ビルドできるとは思わない ❏ 独自進化をしすぎないように注意 ❏ 共通化の意味がなくなるような進化はさせない 81

82.

設計の利点 / 欠点 利点 欠点 ❏ ❏ ❏ ❏ ❏ コードが難読 アップデート対応容易 新機能の横展開容易 全体の把握が容易 Jenkins の学習コストが 低い ❏ 原因はコード内の複数バー ジョン分岐 ❏ 属人化しやすい ❏ コア部分を一部の人しか触 らなくなるため 82

83.

負の遺産 ❏ ifdef に頼り切った難読コード ❏ 特定バージョンのみ実行する処理 ❏ 追加意図が不明になった処理 対策: 全社的に不要な Unity バージョンは消す 専用処理を消しやすくしておく 83

84.

アプリビルドまとめ ❏ なるべく複数バージョンで共通化する ❏ 実は Unity からビルド出力する処理は Unity4 ~ Unity2019 まで変化は少ない ❏ バージョン固有の処理は削除しやすくする ❏ 負の遺産はどんどんたまる 84

85.

Asset Bundle ビルド 85

86.

アセット バンドル総数

87.

280,000 files 7 GB

88.

760,000 files 28 GB

89.

これと 戦います

90.

Asset Bundle ビルド更新の方針 ❏ クリティカルな問題のみ更新対応する ❏ 変更しなくていいところは変更しない ❏ Asset Bundle のロード処理は引き継ぐ ❏ Asset Bundle のビルド処理は変更しない ❏ 旧 Unity バージョンのまま動くところはそのままにする ❏ ロードまわりに不具合が出た際に問題切り分けしやすくする ❏ Asset Bundle のバージョン管理は更新する ❏ Git から Git LFS へ ❏ ところでみなさん何使っておられます? 90

91.

ビルド処理を変更しない理由 現状のプロジェクトでの運用 ❏ 施策ごとに分離してビルド ❏ アセットのパスを指定してビルド ❏ BuildPipeline.BuildAssetBundle() を使用 ❏ 現在は Obsolete になっているのでいつかは.. Single Manifest などを導入すると 運用フローの大幅な変更が必要になるため ビルドフローは変更しない 91

92.

アップデート対応時の諸問題 ❏ 依存関係情報がない ❏ 依存調査しながらビルドすると処理時間が膨大すぎる ❏ そもそもビルドすべきアセットがわからない ❏ 運用から Merge のどれをビルドすべきかはプロジェクト進行に依存 ❏ どれが fix されたアセットかがわからない 対策:全部ビルドしよう 92

93.

全 Asset Bundle ビルド ❏ Deploy 用リポジトリからビルド済みアセットを取得 ❏ 取得したアセットのパスから元アセットリストを作成 ❏ リストにあるアセットを全部ビルド 依存関係がわからなくても、 全部ビルドしたら問題解決! 93

94.

とはいかない

95.

そう 数の暴力

96.

Asset Bundle ビルド時間問題 ❏ Asset Bundle の数は約760,000 ❏ 1 秒/ Asset Bundleで処理すると約8日かかる ❏ 実際は1秒以上かかる ❏ 何も考えずにやったら「終了までxxxx日」って出た ❏ iOS / Android を分割してビルドしても約4日 遅すぎて無理 96

97.

Asset Bundle ビルド並列化 ❏ やっぱり物量には物量で対抗 ❏ アセットをリストアップ ❏ ビルドリストを12分割 ❏ 1プラットフォームあたり12並列でビルド ❏ 全 Asset Bundle ビルドするのに20時間 ❏ 修正確認ギリギリ許容できる 97

98.

しかし半年後

99.

ビルド時間が再度限界に到達 ❏ アップデート対応終盤にはビルド頻度増加 ❏ 各ゲーム内イベント施策を Unity 4 / 2018 並行デバッグでさらに増加 ❏ Git リポジトリサイズ増加で 処理にかかる時間も増加 ビルド時間3日に突入、再対応へ 99

100.

さらなる高速化 ❏ 差分ビルド化 ❏ ビルド時ファイル毎に Hash をチェック ❏ 単体ファイルは AssetDatabase.GetAssetDependencyHash ❏ フォルダは子ファイル全てに AssetDatabase.GetAssetDependencyHash ❏ ビルドアセットの内部アセットも Hash 保存 ビルド時間3日→5時間 今度こそ対応完了 100

101.

遠くない未来の課題 ❏ 当然 次のアップデートまでにアセットは急増 ❏ 当然 さらなる高速化が必要 ❏ バージョン管理方針の変更が必要そう ❏ Git LFS がファイル数の増加に弱い ❏ 通信速度が出なくて遅い ファイル数減らさないと... 101

102.

Asset Bundle ビルドまとめ ❏ ビルドフローは変えなくても対応可能 ❏ Obsolete なのでバージョンアップ後に切替え推奨 ❏ ビルド機能はどんどん良くなってるので切替え推奨 ❏ 規模増加にともなってビルド高速化が必須 ❏ Unity の外側での対応も有効 ❏ 新しいビルド機能の方が最善最速とは限らない 102

103.

全体まとめ 103

104.

全体まとめ ❏ アップデート作業はお早めに ❏ 対応方針はサービス等の規模に応じて ❏ 今後の課題 ❏ 一部 Legacy 機能の排除 ❏ 定期更新が可能な環境構築 104

105.

ご清聴 ありがとう ございました 今後も数の暴力には屈しない... 105