【Unity】「サイバーエージェント×Unity×デザイン塾」レポート その２

* [【Unity】「サイバーエージェント×Unity×デザイン塾」レポート その１](http://qiita.com/baba_s/items/b32b2684355768f66a73)
* [【Unity】「サイバーエージェント×Unity×デザイン塾」レポート その２](http://qiita.com/baba_s/items/86ef52eb26c44d526133)

# サイバーエージェント×Unity×デザイン塾

http://www.creativevillage.ne.jp/lp/cyberagent/

# ウチ姫におけるビルド環境自動化と実行時負荷軽減手法

アメーバ事業部 ウチ姫開発チーム エンジニア　
渡邉俊光 様

## 自己紹介

* 2012年新卒入社
* 研修後、開発が始まったばかりのウチ姫にUnityエンジニアとして配属
* UIや描画回り、アプリビルドの自動化などを担当

## AssetBundle作成時の効率化方法

* Unityでは外部ファイルの配信方法としてアセットバンドルという機能が用意されている
	* Unityで使えるものは簡単にパックできる

* アセットバンドルの問題点
	* ビルドする必要のあるファイルかどうかがわからない
	* 依存関係を含むビルドをする場合は複雑なスクリプトが必要
	* プラットフォームごとに個別でビルドする必要がある
	* （これらはUnity5で改善されています）

* アセットバンドルのビルド手順
	* スクリプトの呼び出し
	* シェーダなどの共通ファイルをビルド
	* `BuildPipeline.PushAssetDependencies`
	* 指定フォルダ以下のサブフォルダ内をすべてハッシュ計算し、  
変更があったものやUnityバージョンが違うものをビルド
	* `BuildPipeline.PopAssetDependencies`
	* 終了
	* ビルドしたアセットバンドルをコミット

* 差分ビルドの方法
	* ビルド結果を一覧化するためにエクセルのシートに自動出力
	* モンスターなどのタイプごとにシートを分けている
	* 中のセルを自動更新している
	* ライブラリにはNPOIを使用
	* カラムは下記のような感じ

```csv
モンスターID,iOSビルド,iOSビルド時間,iOSハッシュ,Androidビルド,Androidビルド時間,Androidハッシュ
```

* Unity5ではこんな面倒しなくていい
	* `BuildPipeline.BuildAssetBundle`を呼べば変更があるファイルだけビルドされる
	* スクリプトの数値一つ変えるだけでも確実にビルドしてくれる
	* ビルド結果は戻り値のマニフェストを確認すればいい

## ビルド環境ごとのアプリ出力までの自動化

* 環境に合わせたアプリ出力のフロー
	* モバイルアプリでは運用のために複数のサーバーが存在する
	* Develop、Staging、Productなど
	* 環境ごとに設定を変えるためのエディタ拡張をウチ姫で使用

* 一連のフロー
	* 環境ごとの設定を`ScriptableObject`に保存してリポジトリにコミット
	* その設定を使用してJenkinsのUnityでバッチビルド
	* HockeyAppに環境ごとにアップロード
	* 申請ipaはApplication Loaderで送信


* 環境ごとにビルド設定を行う
	* 切り替え用の`EditorWindow`を作成
	* saveを押すと`ScriptableObject`にデータを書き込む
	* すべてC#で実装することでビルド時の環境違いを減らす
	* レイヤー、タグ、シーン名も定数にしてC#ファイルを同時出力
	* BuildSettingsの内容も外部ファイルに逃がしている

* Jenkinsジョブ実行
	* `-batchmode -executeMethod 実行メソッド STG,iOS -quit`
	* ビルド時に引数を以下のメソッドで取得
	* `Environment.GetCommandLineArgs`
	* これで複数の追加プロパティをbatchmodeでUnityのメソッドに送ることができる

* HockeyAppとは
	* Android,iOSのアプリケーションを配信するサービス
	* 12月にMicrosoftに買収された
	* 端末のブラウザから簡単にインストールができ、バージョン違いも確認可能

* HockeyApp登録
	* JenkinsのHockeyApp Pluginを利用してipa,apkをアップロード
	* 申請版を含め各種環境ごとに上げることで全環境の最新版を確認することが可能

* クラッシュ調査
	* HockeyAppSDKを導入することでバージョンごとのクラッシュ情報を送信してくれる！
	* クラッシュした端末の端末名やOSも送信するので簡易クラッシュ解析としても利用可

## 実行時の描画負荷を軽減する際に必要な技術と考え方

* ウチ姫の初期ではiPhone4で60FPSを目標に実装
	* どのゲームでもボトルネックなる要素
		* フィルレート（主に透過周り）
		* SkinnedMeshのポリゴン、ボーン数
		* シェーダ
		* DrawCall

* フィルレート
	* GPUの性能の測定値
	* 描画ターゲットのピクセルの書き込み速度
	* 不透明で描画できる3Dより透過になりがちなUI側で非常に消費する
	* UnityEditor上のProfilerでは差が出ることはほぼないので注意

* ベンチマーク
	*NGUIを用い、DrawCallが1の場合の表示枚数とFPSの関係を調査

* 結果
	* 不透過シェーダで描画するとiPhone4,4Sともに相当量出すことが可能
	* 透過シェーダの場合iPhone4,4Sで5倍以上の性能差がある
	* 透過する必要がないものはUnlit/Textureを使っている

* ウチ姫では
	* 背景画像など、透過する必要のないオブジェクトはUnlit/Textureを利用
	* 画面全体描画する必要のあるデザインは極力避ける
	* 最近はGPUの性能が非常に高いのでここまでやる必要はもうないかもしれません

* 描画領域の確認方法
	* SceneビューのRGBをOverdrawに変更
	* 多重に書き込まれているところがわかる

## まとめ

* アセットバンドルはシェーダファイルはまとめ、変更を検知するシステムを作成
* ビルドフローを自動化し、申請時の負荷を削減

## 質疑応答

* 最適化に関して苦労したこと
	* 最適化するまでに3回ほどUIを0から作り直した
* アセットバンドルのメモリの展開に関して苦労したこと
	* リソースマネージャーのコンポーネントを作成して  
リファレンスカウントが0になったら`Unload`するような仕組みを作っている
	* Inspectorで`Load`されているアセットバンドルをすべて見れるようにした
	* メモリ不足で困ったことはほとんどない
* ドローコールに関して基準値は設けているか
	* 当時は20~30あたりまでと気を付けていた
	* エフェクトは問題ないがステージの背景とかは気を付けてもらった
	* バッチが効くような作りにしてもらった