「COLOPL UnityNight」に行って来ました(その2)
Unityとスマートフォンアプリの最適化 - Kuma the bear準備室 栗原 秀行さん
(追記 2012/04/21)
スライドが公開されたので追記。
Kuma the bearとは・・・
- オフラインで動作するアプリである事
デバイスや通信速度に依存しないプラットフォームとして。
できるだけ多くの端末をカバーするため。
- グローバルである事
App Store / Google Playのプラットフォームで展開する以上、ローカライズも積極的に。
- ゲームとして面白いものである事
Kuma the bear新タイトル「むしアミ!」
コロプラ、スマートフォン向けゲームアプリ『むしアミ!』を提供開始 〜家を侵略する「むし」を退治しろ!ディフェンス系シューティングゲーム登場! | 最新情報一覧 | 株式会社コロプラ【位置ゲーで毎日の移動を楽しく】
http://colopl.co.jp/news/pressrelease/2012040901.php
Kuma the bearタイトルのメンバー
- 基本はスモールチーム(3-4人)
- プロジェクト初動は、
- エンジニアがプロトタイピング
- ディレクターとデザイナーが企画を固める
- 後半に別のプログラマーがジョイン
意思決定は早く!
- プロジェクト終盤は皆でゲームバランスの調整
- みんなUnityを使っている
- メンバの特性を活かす
メンバの特性
- iOSネイティブ周りに強いiTunes Connect
- 3Dに強いコンシューマあがり、GLとか分かってる
- Androidネイティブ周りに強い
- Unityそのものに超詳しい、AssetStoreオタク
- Unity EditorScriptでツール作り
- チームメンバーのUnityに関するナレッジはフラットに!
作る上での基本構成
基本は1シーン
- 直ぐに始められるゲームを目指すために、必ずワンシーンにする
- シーンロードは避けるように務める
- そのために Resources.Load/UnloadUseAsset を使ってメモリロードはフレキシブルに
プロジェクト毎にツールを作成
- プロジェクトに応じたツールは EditorScript・Shell などで作成する
- ゲームパラメータの調整には必須
EzGUIは使っています
- 悪名高いライブラリですが、パフォーマンス改善・省サイズには効きます
- 上手く使えばMVCモデルにできてスッキリ
ひとつのバイナリで多言語に対応
- EzGUIの機能を使って、ワンバイナリで多言語対応を実装
Nativeのソースは流用しまくる
リズムコイン 〜ここでハマった〜
問題 その1.全体的に遅い、もっさりしている
→Profilerで見ると、CPU UsageがほとんどPhysics関係
疑いその1.Mesh Colliderの頂点数が多いんじゃない?
Primitive Collider ではどうしようもできないので、8角形のCollider用のMeshを別途作成
→結果、ほんの少しだけ軽くなったけど、基本は変わらない!
疑いその2.そもそもコインが重くて場に残り過ぎなのが問題では?
→コインの Physics Material の摩擦係数を軽くして、土台から流れやすくする事で、結果的に衝突回数を減らせて、Physicsの抱える問題を解決!
↓
これが正解だったけど、ゲームバランスを再調整する必要が発生
パフォーマンス調整でゲームバランスへの影響をする事は多いので段階的にパフォーマンスチェックもすべし!
問題 その2.フィーバーモード突入時に一部Android端末で落ちる
→クマの後ろで出している ReanderTexture が原因じゃないか?
どうやらテクスチャの初期化で落ちるのは GalaxyS で再現性が取れた
→動的にスクリーンのMaterialに SetTexture をしていたのが問題
・初期化のタイミングで RenderTexture を割り当てて、内部的に切り替える様にした
RenderTexture の使用そのものを控えるべきですが、その他 IS03 など一度に複数の RenaderTexture が使えない端末もありました。GPUに依存する所が大きいです。
わっさーゾンビ! 〜ここでハマった〜
問題 その1.ここでも全体的に遅い、もっさりしている
→ Skinned Mesh Renderer を使っているし、 Draw Call 数はゾンビの数だけ発生。あと、やはりPhysicsが重い。
→ボーン入りのキャラクターアニメーションを使っている都合上、 SkinnedMeshRenderer を切ることは不可能
→キャラクターはRigidBody同士の衝突となっているが、既にプリミティブの Collider となっている
→やや乱暴だが、Time設定の FixedDeltaTime を調整する事で物理エンジンの演算回数を減らす事で対応。その他、アプリケーションのフレームレート上限を30に指定。描画コスト減
Unity Script Reference – Time.fixedDeltaTime
http://unity3d.com/support/documentation/ScriptReference/Time-fixedDeltaTime.html
アクション性・物理特性がゲーム性に影響しないタイトルにのみ使用可能
問題 その2.実時間ベースでのゲームバランス調整は正直きつい
→ツールやシミュレーションベースの方法を使ってテスト
→Time.timeScale での設定でx倍速モードでテスト出来るように構成しておく
→シミュレータ上からゲームの進行ログをConsoleだけなく、CSVではける様にしておく。経過時間とイベント発生をグラフ化して、ゲーム内の進行状況に偏りが出ないようにする
問題 その3.iOS上でプチフリが発生(iPad/iPhone 3GS/iPhone 4)
→データ保存のホーリング中に発生
→ゲームの特性上、PlayerPrefsが肥大化、またゲームの特性上、更新頻度が上がってしまった事が原因
→PlayerPrefsの保存は必ず処理が一時停止するため、まずは保存の項目の省サイズ化
PlayerPrefsは非同期で無い事に注意
→ OnApplicationPause と OnApplicationQuit できちんとセーブしてあげれば、問題無し
ポーリングでデータ保存すると、壊す可能性も否定出来ないため要注意!
むしアミ! 〜ここでハマった〜
問題 その1.ここでも全体的に遅い、もっさりしている
→Skinned Mesh Renderer 使っているし DrawCall 数はむしの数だけ発生。あと、やはりPhysicsが重い
→Physicsは衝突はさせていませんが、Triggerには使ったりしています
→Physicsの計算を端折ったり、FPSを落としたりできない!
→やられポイント取得などのエフェクトの拡大、縮小などをモデルとアニメーションが行われていたため、そこでの DrawCall をバッチングさせるために、テクスチャのOffsetアニメーションなどで実装。演出もEzGUIで実装
→Draw Callのバッチングが効くケースと効かないケースをしっかりと把握しておく事
→全体的に敵の流れが良くなるように、ゲームのバランスを調整
→結果として真っ向勝負しないようにして、パフォーマンスを改善
問題 その2.全ステージ300ステージ
→Inspector上からの編集は正直難しい。CSVが必要でやる事に決めた
→Inspector上からの調整は誤入力が起きそうで正直怖い
→Export/ImportスクリプトをEditorスクリプトで調整
→Excelでグラフ化しながら大雑把に調整
→300ステージでのパラメータ入力にあたり、難易度にゆらぎ・誤入力が出ないように、Editorスクリプト上でバリエーションを実装
バリデーションでエラーが出たらコンソールに出力
Inspectorでの配列操作は50くらいまでが上限かと、、
それ以上のパラメータはCSVとの連携が可視化の意味でオススメ!
EzGUI Localize Tips! その1
- フォントスプライトシートの出力はMacなら BMGlyph か GlyphDesigner で
- 両方ともEzGUI用のExport設定有り
- 文字の装飾はGlyphDesignerが綺麗に出せるので、こちらを推奨します!
EzGUI Localize Tips! その2
GUIのスプライトシートは無圧縮16bit画像つき、メモリの圧迫サイズが大きいのでシステム言語環境に応じて、 Resources.Load でMaterialのMainTextreを変更。全言語で共通のUIはそのまま共有。
【コード例】
Material LocalizeMaterial; if (Application.systemLanguage != SystemLanguage.Japanese) { Texture2D t = (Texture2D)Resources.Load("LocalizeResource/GUILocalizedEnMaterial", typeof(Texture2D)); LocalizeMaterial.mainTexture = t; } else { Texture2D t = (Texture2D)Resources.Load("LocalizeResource/GUILocalizedJpMaterial", typeof(Texture2D)); LocalizeMaterial.mainTexture = t; }
Android メモリ小技
Androidの実行メモリの使用量につき、OSによりActivityが終了させらる事が有ります。
メモリの使用量は、AdmobなどNativeまわりも考慮してUnity単体で100MB以下におさえる必要が有ります。
端末のタスクマネージャーに表示されている数字については、端末毎に異なった数字が返ってくるので当てになりません(Galaxy S2とか)
以下のコマンドで確認しましょう
adb shell top | grep package name
adbを使えば、正しいメモリ使用量が取得できますので、adbを使って実際のメモリの使用量として参考にして下さい。
プロジェクトの序盤ではUnityから直接APKを作っていて問題ありませんが、後半では、Native側の連携が重要となり、なおかつ実機テストが必要となります。
いちいちEclipseを通してのパッケージングは面倒臭いので、UnityBuild後に、Antでコマンドビルドするようにしました。
UNITY_PROJECT=/Documents/unity/title/ ECLIPSE_PROJECT=/Documents/Eclipse/title/ cp -r $(UNITY_PROJECT)/Temp/StageArea/assets $(ECLIPSE_PROJECT) ant clean ant release date
InAppBillingのテストなど署名付きビルドをする場合には署名のパスフレーズも Build.properties に書いておけば入力しないで済むので超便利!
まとめ
1.パフォーマンスがらみは正面から勝負するよりも分析。またSCMで必ず遡れるゆ鬼して原因の差分を比べる
Profiler/Instruments/OpenGL ES Perfomance Detective/adbを駆使
2.特定の問題の出やすい端末を把握しておく事が必要
IS03/Arrows X/Infobar/Galaxy/iPhone 3GS ... more
3.UnityのEditorScriptはエクスポート・インポートだけでなく、バリデーションにも使える。
Excelとの連携にも便利になるので、プロジェクト毎でも起こす価値がある。
SerializeしてInspectorでの調整はべんりだけど、数の多い配列はCSVも考慮して。
4.ゲームとしての面白みにこだわるための近道は常に確保。AssetStoreは眺めるだけでも楽しいもんです。
5.ツールを作るのはプログラマ的に、超楽しい。