「もののけ大戦“陣”」製作事例

59,781 views
59,462 views

Published on

1 Comment
152 Likes
Statistics
Notes
No Downloads
Views
Total views
59,781
On SlideShare
0
From Embeds
0
Number of Embeds
2,743
Actions
Shares
0
Downloads
411
Comments
1
Likes
152
Embeds 0
No embeds

No notes for slide

「もののけ大戦“陣”」製作事例

  1. 1. 「 もののけ大戦“陣” 」制作事例 Unityで美麗2Dゲームを作る秘訣 (2012/09/18 加筆、修正) 2012/08/23 株式会社 スパイクチュンソフト 時村 良平
  2. 2. 修正内容 • • 2012/09/18 ・シーンキャッシュ全般について、enabledとなっていたのをactiveに修正 ・AssetBundleの多重リンクについて追記(p120) 2013/11/27 ・シーンキャッシュのリスクを追記(p35) ・NGUIの描画順について 追記(p45) ・AssetBundleとシェーダの関係についての誤りを追記(p112)
  3. 3. 自己紹介 コンシューマ系ゲームのころからの ゲームプログラマ 主にノベル系の製作に参加
  4. 4. アジェンダ • • • • • • 開発環境 高速シーンロード ハイクオリティな2Dエフェクト テクスチャ設定 AssetBundle TIPS
  5. 5. 開発環境
  6. 6. 開発期間 約7か月 人数 10人前後
  7. 7. スクリプトはC#で統一
  8. 8. バージョン管理は Team License(Asset Server)
  9. 9. メタファイルやAssetの移動を スムーズに管理できる エンジニアじゃなくても簡単 Asset Server お勧め
  10. 10. 高速シーンロード
  11. 11. Unityのシーンの特徴 ・「1シーン=1アセット」 ・「スマホだと、シーンのロードが遅い」
  12. 12. 「1シーン=1アセット」 →複数人数で同じシーンを編集すると衝突する →シーンを分割しないといけない しかし 「スマホだと、シーンのロードが遅い」 →シーンを分割してはいけない?
  13. 13. シーンロードを高速化すれば解決!
  14. 14. シーンロードのボトルネックは何か? UnityのProfilerで確認 どうも「シーンロード」ではなく 「前シーンの破棄」がボトルネック
  15. 15. たぶん Resources.UnloadUnusedAssets (未使用のアセットを オブジェクトを全検索して解放する) が重いのと同じ原因っぽい?
  16. 16. 実際、 LoadLevelAddtiveで 前の シーンを破棄しないと シ ーンロードは早い
  17. 17. 対策
  18. 18. シーンキャッシュ
  19. 19. コンセプト 一度ロードしたシーンは破棄せずに メモリ上にキャッシュ 二回目以降は それを使いまわす
  20. 20. 既存のシーン管理 シーン1 LoadLevel シーン2のロード シーン1のアンロード シーン2 シーン1 シーン2
  21. 21. シーンキャッシュ シーン1 LoadLevelAddtive +キャッシュ処理 前のシーンは破棄しない シーン2のロード シーン1のアンロード シーン2 シーン1 全オブジェクトのactiveをfalse にして、残したままにする シーン2 シーン1
  22. 22. シーンキャッシュ シーン2 シーン1 二回目の以降のシーンロードでは、 LoadLevelはいらない。 キャッシュ制御 (EnabledのON・OFFを切り替える) だけ シーン2 シーン1
  23. 23. 「もののけ大戦陣」でのシーン管理 ロードでされたシーンは、子要素を Hierarchy直下に移動し、 active状態を復帰 アンロードでされたシーンは、 ルートオ ブジェクト以下にオブジェクトを移動し、 active状態を、記録したのちfalseに
  24. 24. シーンキャッシュどうやる • 加算でシーンを管理する必要がある • Unity高橋さんのシーン加算スクリプ ト を改造
  25. 25. 共通となるシーン • さらに全シーンで共通な仕組みがあると便利。 ゲームデータの管理をはじめ、 サウンド とかの○○マネージャーとか システム ダイアログとか・・・・
  26. 26. 共通となるシーン • Unity大前さんがGameJam2012で使った考えを拝借 常に加算したいシーン内に、目印になるタグをもつ空のオブジェクトをつくる シーンロード時に、目印がなければ「目印をもつシーン」を加算シーン。 目印が既にあれば、加算シーンしない。 これが役立つのは主にエディタ上
  27. 27. 通常のシーン加算では ロードする順に、シーンが追加される エディタ上で編集中の シーンをいきなりロードしても・・・ 読み込んでおきたいシーンが ロードされずにバグる
  28. 28. Commonシーン エディタからどのシーンを起動しても 読み込んでおきたいシーンは 自動 的に即座に加算する 「もののけ陣」では、これをCommonシーンとした。 他のシーンからアクセスされるようなオブジェクトはCommonシーンに起き、 各コンポーネントにはSingletonを使ってアクセスすると便利
  29. 29. Singletonのサンプル public class Hoge : MonoBehaviour { static Hoge instance; public static Hoge GetInstance(){ return instance; } void Awake(){ instance = this; } }
  30. 30. シーンキャッシュの結果
  31. 31. シーンロード時間はほぼゼロに! キャッシュ前(最初の一回)でも、1~2秒 (ただし、通信による待ち時間は普通にかかります) 各画面ごとにシーンを分割して分担。作業効率UP!
  32. 32. 「もののけ大戦陣」でのシーン管理 Commonシーン。常に存在する 各オブジェクトにはsingletonを使ってアクセス。 Scene Mergerの下に 各シーンをキャッシュして管理 各シーンのキャッシュ管理をする ルートオブジェクト ロードでされたシーンは、子要素を Hierarchy直下に移動し、 active状態を復帰 アンロードでされたシーンは、 ルートオ ブジェクト以下にオブジェクトを移動し、 active状態を記録したのち、falseに
  33. 33. ただし、 手軽に作るにはちょっと 向かない 「Awake()やStart()など Unityの基本的な仕組みが使えない」
  34. 34. さらに、シーンの初期化・終了は 自前で管理する必要がある シーン切り替え時に、自前で SendMessageするなどして対応した C++でコンストラクタとデストラクタを 書くような面倒さが……
  35. 35. 追記 リスクについて 「やってみたけどバグの温床になる!」 という話を聞いてたりします。 特に、メモリの肥大化があるようです。実際、自前 でリソースのメモリ管理することになるので、リスク は大きいです。 Unity4による高速化や、最近の端末自体のスペッ クアップもあるので、もはや迂闊に手を出す手法で はないかもしれません。 高速化と開発効率は反比例するので注意を。
  36. 36. ハイクオリティな2Dエフェクト
  37. 37. もののけ大戦陣のエフェクト
  38. 38. 半透明を多用 特に、パーティクルを中心に 加算エフェクトを使うことで キラキラした感じを出してる 個人的には加算重要
  39. 39. どうやったか?
  40. 40. NGUI+Particle+Animation この三つと
  41. 41. 努力
  42. 42. NGUI
  43. 43. NGUIとは Unityの2Dプラグインの スタンダード GUI系の機能がメイン。 ただのスプライト描画 にも使える AssetStoreで購入可能
  44. 44. NGUIそのままでは使えなかった ちょこちょこ拡張
  45. 45. 一番の問題 描画順の制御 *追記 NGUI3.0以降は 解決済みというウワサ
  46. 46. NGUIのPanel内の描画順 同一マテリアル(アトラス)なら、 Depthの値どおりに描画される 1 2 3 4 5 6 7 8 異なるマテリアルが混ざると、 描画順が崩れてしまう 1 2 3 4 5 6 7 8 1 3 5 7 2 4 6 8 1 3 5 7 1 3 5 7 2 4 6 8 2 4 6 8 同じマテリアル同士では Depth値は正しく機能する マテリアルごとにグループになっ ているっぽいが、 グループ間の 描画順は制御しづ らい ↑この場合もあれば ↑こっちのパターンもある
  47. 47. NGUIの描画の仕組み 1 UIDrawCall その1 UIDrawCall その2 2 1 3 4 3 2 5 6 5 4 7 8 7 6 8 実はNGUIの各オブジェクト自体は描画処理をしない。 描画を担当する UIDrawCallというオブジェクトを裏で自動生成している。 UIDrawCallはマ テリアルごとに作られるため 描画順はマテリアルごとに区切らざるを得 ない
  48. 48. NGUIの描画の仕組み Geometryにすると NUGIが自動生成する UIDrawCallオブジェクト が表示される
  49. 49. いろいろ解析すると、 同一 Panel内で マテリアルが入り混 じる描画は NGUIの仕様外 つまり、 ・フォント専用マテリアルを混ぜる ・加算シェーダのマテリアルを混ぜる とかすると、描画順が制御しづらい! Panelを逐一つけて、Z値をうまく使えば解決はするが・・・
  50. 50. 違うマテリアル同士でもDepthの値で 描画順が制御できるように NGUIのソースコードを修正 UIPanelのソースを中心に… マテリアルが違ったら UIDrawCallオブジェクトを増やす 各widetのZ値は0固定にし、Depthに比例した値を UIDrawCallオブジェクトのZ値にoffsetする Unityは半透明描画物はZソートされるのでそれを 描画順制御に利用 Panelが違うものの描画順はPanelのZ値で制御 ・・・といった感じで改造 詳細は省略・・・けっこうややこしい
  51. 51. 正直、これをしないと 2Dゲームは厳しいと思う
  52. 52. NGUIはここが非常にもったいない
  53. 53. その他、NGUIの機能拡張
  54. 54. タイルド+スライスド機能 最初に拡張しようとした部分 英語ができずに、結局製作 者への依頼を諦めた 英語できるといいね
  55. 55. アスペクト比固定のフルスクリーン表示 アスペクト比が崩れない 最大の大きさで描画される アスペクト比(タテヨコ比)が バラバラのAndroidの対応 カメラをうまく使うのがコツ カメラ1:黒でクリアするだけ カメラ2:ビューポート (camera.rect)を利用して、指 定の範囲に描画をする 余りは 黒枠
  56. 56. Y座標をアニ メーション 「UVスクロール」 (最新のNGUIでは追加されてる?) UV値をアニ メーション 画面 画面外に大きくはみ出る 巨大スプライト描画は Android一部端末で 負荷が大きかった UVスクロールに変更
  57. 57. 「A8bitテクスチャでのフォント描画」 (すでに最新のNGUIでは似たような機能があるので不要かも) A8描画用のシェーダを作成 メモリサイズは1/4に 2048×2048のテクスチャなら フォント サイズを22~24くらいにすれば メモリ 消費4Mで8000文字近く入る フォント ワークス製フォントで 全文字入ったの で 日本語表示は実質解決
  58. 58. NGUIの高速化
  59. 59. newを減らそう たとえば、頂点データを一時作成する配列を 毎回newしてる 計算のための一時バッファなら、 staticなバッファを作って それを 使いまわしてもOK
  60. 60. 時間によって 処理回数が増えるところを調整 前フレームとの時間差ぶん ループ回数が増えるところがあったり 処理が落ちるほど、さらに重くなるという
  61. 61. 拡張による問題点
  62. 62. 最新バージョンのNGUIとの マージを諦めた この辺は今後の課題
  63. 63. Animationエディタ
  64. 64. UnityデフォルトのAnimation • 3Dモーションだけではなく、Flashのような 2Dのキーフレームアニメにも使える。 • EventキーでSEつけたりと柔軟に拡張可能
  65. 65. Animationエディタには いく つか問題が • Hierarchyで名前や構造を変えても、キーは変 更されない • boolとfloatにしかキーが打てない(intは無理) • カラーの値などを変えても描画に反映されな い? • キーのコピーができない! と、なかなか手ごわいです
  66. 66. 「Hierarchyで名前や構造を変えても、 キーは変更されない」 ↓ 後から構造を変更するとキーを打ちなおしになる ↓ 事前に構造を決める! ある程度の慣れが必要 既にキーを打ったものを変更すると壊れるが 「追加」はOK
  67. 67. 「boolとfloatにしかキーが打てない(intは無理)」 ↓ intをfloatに書き換える が、結局intのパラメーターに キーを打つ必要が生じなかった
  68. 68. 「カラーの値を変えても描画に反映されない?」 NGUIの拡張が必要。カラーに限らない話。 Unityのアニメーションは、メンバ変数を直接書き換えるっぽい →setやエディター拡張による定義は無視される ↑ こういうの mColorの値だけ書き換えられて、mChangedのフラグが立たない 毎フレームカラーの値の変化を監視する処理を組み込んだ。
  69. 69. 「キーのコピーができない」 ↓ 諦めた AssetStoreにもサポートプラグインはない模様。 Editor拡張のスクリプト書くしかない? Unityへのリクエストはけっこう前からある模様…… 4.0に期待!!
  70. 70. その他、細かいバグっぽいものの対処 ・回転のConstant変化にバグ →Scriptで解決。 のちにUnityから対 応策発表 。 ・Eventでセットしたアセットは、キーを消しても リンクに残ってしまう →NULLをセットした後キーを消す
  71. 71. 一度長くしたキーフレームの最大長を 短くできないバグ ↓クリーンナップスクリプトを書いて解決
  72. 72. けっこう問題は多いですが ゲームの見た目そのままにアニメーション編集 できるのは便利! うまく使えば、十分に使い物になる
  73. 73. Particle
  74. 74. Particle Shuriken未使用 (リリースが 開発途中だったため) Legacy Particleで割と安定。 そのままで使える感じ。 省テクスチャで豊かな表 現が可能な反面、 速度的な負荷が高くなり がちなので注意。
  75. 75. 描画パフォーマンスについて
  76. 76. Unityというかスマホの 2D描画パフォーマンスについて • GPU処理で意識すべきは ドローコール フィルレート • CPU負荷になりがちなのは サイズの大きい newやPrefabのInstantiateなど ・その他 描画に使うリソースのロードは事前に しておく
  77. 77. 半透明使うなら 特にフィルレート重要 ・平たく言うと「ピクセルを画面に描く速さ」 画面の解像度が高い=たくさん描きこむ=遅い このせいで、iPhone4はiPhone3GSよりも遅い (iPhone4sはGPU性能が上がってるので早い)
  78. 78. フィルレート対応 第一に 「ピクセルを書きこむ面積 を 減らす」 ……と、アーティストに伝えて エフェクトを作ってもらう。 特にパーティクルは肥大化 しがちなので注意。 UnityのOverdrawで確認もできる 最終的には実機で確認しつつ調整 SceneビューでOverdrawを選択 多重に書き込まれているところがわかる
  79. 79. フィルレート対応 第二に 「シェーダをMobile用に」 UnityはMobile用に、 処理の軽いシェーダを用 意している。 パーティクルもちゃんと Mobile用を使うこと。 NGUIであれば、 Clip系の シェーダは処理が重 いとこ ろでは使わない。
  80. 80. もろもろの苦労を経て・・・
  81. 81. ワークフローさえ固まれば アーティストはエフェクト作成に専念でき、 エンジニアはトラブルシューティングに専念できる Unityの強み「動かしながら即座に編集」 が生きてくる ゲーム制作での強敵 「イメージを伝える」という必要がなくなるので 非常に効率的
  82. 82. 実際は・・・・・・ パラメーターを反映した ゲームっぽい複雑なフローは スクリプト必須 エンジニアも頑張りましょう
  83. 83. 複雑なフローの「一部」
  84. 84. ・・・playmakerとかで 効率化できたかも
  85. 85. テクスチャ設定
  86. 86. 2Dテクスチャの インポート設定は こんな感じ
  87. 87. Texture Type を Advancedにする (細かい設定が面倒なら、 GUIで) テクスチャフォーマット 圧縮しないならNONEを設定 (グレーで選択不可の場合はそのままでOK) Defaultを設定 チェック外す 特にGenerateMipMapをONにすると 画像がボケたあげくメモリ消費が増えます 使わないのでClampとRpeatどちらでも可 (とりあえずClamp) Bilinearを設定 2Dでは 関係ないので一応0を設定 圧縮に関しては、次項に詳細 テクスチャサイズよりも大きい値を設定
  88. 88. テクスチャの圧縮(減色)に関して
  89. 89. 基本、スマホでは テクスチャ をロードすると メインメモリが 消費されます。 テクスチャのサイズは ここに表 示される。 pngなどのもとのファ イルサイズ とは異なるので注 意。
  90. 90. 2Dは3Dよりも テク スチャサイズが 肥 大化しがちです テクスチャ一枚で16Mも消費?
  91. 91. サイズ削減のため、 圧縮しましょう 16Mが2Mまで縮んだ
  92. 92. 16bit系の圧縮なら とりあえず半分のサイズ になります。
  93. 93. ここを切り替える
  94. 94. それ以上の圧縮をする場合
  95. 95. Automatic Compressed これでいい感じにしてくれる?
  96. 96. とはいえ、 圧縮(減色)は画質が劣化 するので、 用途によって細い設定が 必要な場面も多い
  97. 97. 圧縮設定詳細
  98. 98. AndroidとiPhoneで フォーマットが違います ( Unityとは関係なく、各端末の仕様)
  99. 99. おまけに、Androidは 機種ごとにフォーマットが 違います
  100. 100. iPhoneは 「PVRTC」
  101. 101. Androidは 「ETC」が唯一の共通フォーマット ただし、αチャンネルなしの画像 にしか使えません DXT、ATCなどは 機種によって未対応の場合あり
  102. 102. 圧縮する際は、サイズ制限があり iPhoneなら、2のべき乗かつ正方形 Androidは、2のべき乗かつαなし ちなみに 「パーティクルは正方形が必須」
  103. 103. テクスチャ圧縮形式まとめ 非圧縮 圧縮(弱) 圧縮(強)Android 圧縮(強)・iOS α な し α あ り 圧縮(最強)・iOS RGB RGB 24 bits 16bits RGB Compressed RGB Compressed RGB Compressed ETC 4bits*注1 PVRTC 4bits *注2 PVRTC 2bits *注2 RGBA RGBA 32 bits 16bits 共通フォーマッ ト なし *注1 サイズは 2のべき乗が必須 RGBA Compressed RGBA Compressed PVRTC 4bits *注2 PVRTC 2bits *注2 *注2 サイズは 2のべき乗かつ正方形が必須。
  104. 104. けっこう大変なので、 Unityには支援機能がある
  105. 105. 細かい設定しないなら、 先ほどの Automatic Compressed
  106. 106. Androidの圧縮を RGBA 16bitかETCに 自 動的にしてくれる機能 Build Settingsから設定 ローカル設定らしく、 AssetSeverで 共有できないので注意
  107. 107. 2のべき乗じゃないテクスチャを圧縮したい場合 インポート設定の「Non Power Of 2」をいじる None以外を選ぶと テクスチャを2のべき乗サイズ にしてくれる 元のテクスチャサイズは失われるの で、プログラム 等矛盾がでないように注意
  108. 108. 2Dゲームなら、 たいていの メモリ不足問題は テクスチャ の扱い次第 うまく調整しましょう
  109. 109. Asset Bundle
  110. 110. AssetBundleの基本 Assetをサーバーから動的にDLし デバイス上にキャッシュ 動的に ロードできる ソーシャルゲームでは カード画像など 頻繁に追加・更新されるAssetに最適!
  111. 111. AssetBundleの基本 テクスチャやサウンドなどの 単純なリソースだけでなく プレハブやシーンも AssetBundle化できる
  112. 112. AssetBundleの基本 プログラム(スクリプトやシェーダ)は アプリ本体のものが使用される 動 的に更新はできない ・・・Appleの規約のため? バージョン違いにならないように注意 *追記 シェーダはアセットバンドルに含まれる。 最適化についての参考ページ→ https://github.com/keijiro/unity-shader-bundle
  113. 113. AssetBundleの使いどころ カードやバナーなどのTexture さらにエフェクトもプレハブ化して AssetBundle こうすると、エフェクトの更新は アプリの更新いらず
  114. 114. AssetBundleの作成 Editor拡張して作成する。 サンプルはあるので問題なく作れる。 ただし、Android・iPhone形式の他に Editor用に、WebPlayer形式でも作成 (α系の画像が壊れるので)
  115. 115. AssetBundleのロード AssetBundle内に多数のAssetがあると 非同期だとロードが長い (数によっては10秒くらい) 同期処理になるが LoadAllで一気に読んだほうが早い (2秒くらいになった)
  116. 116. AssetBundleのロード • サンプルにある • yield www; • ではなく • while( !www.isDone && null == www.error) yield return 0;
  117. 117. プレハブのAssetBundle化 注意点
  118. 118. AssetBundle内に含まれるデータ AssetBundleから リンク されているAssetは すべ て自動的にパックさ れる。 ExportPackageを使うと、 アセットからリンクされてる アセットがわかる。 Assetを選択して 右ク リック-> ExpoertPackage
  119. 119. 多重リンク AssetBundle「A」とAssetBundle「B」の中に 同じアセットがあった場合、別Asset扱いになる →同時にロードすると、メモリが二倍消費される AssetBundle「A」 AssetBundle「B」 テクスチャA テクスチャD テクスチャB テクスチャE テクスチャC テクスチャC この場合、読み込まれるテクスチャ は テクスチャA,B, D,E, C×2
  120. 120. 多重リンク AssetBundleとアプリの中に 同じアセットがあった場合も同様 AssetBundle「A」 アプリ テクスチャA テクスチャD テクスチャB テクスチャE UI用 テクスチャ UI用 テクスチャ UI用のテクスチャなど、アプリが持ってるテクスチャを AssetBundleで使ってしまうと二重化する。 逆に、AssetBundle のカード画像などを アプリのシーン内のオブジェクトからリン クしている場合も同様
  121. 121. 多重リンク回避 ダミー画像を使う アプリ AssetBundle「A」 テクスチャA テクスチャD テクスチャB テクスチャE ダミー画像 セットしなおす フォント用 テクスチャ 作成時には、8×8などの小サイズのダミー画像を設定し スクリプトを使って、ロード後にテクスチャを張り替える
  122. 122. 多重リンク回避 AssetBundle同士なら、 PopAssetDependencies& PushAssetDependencies を使う AssetBundle「C」 AssetBundle「A」 AssetBundle「B」 テクスチャA テクスチャB テクスチャC ロード時に 自動でリン ク テクスチャD テクスチャE テクスチャC テクスチャC AssetBundle作成時に PopAssetDependencies& PushAssetDependencies で リンク関係を作っておく。 AssetBundle「C」を、「A」「B」より先に読み込むことが必須。 プレハブ や、モデルのテクスチャなどの場合に有効。 詳細は、Unity公式サン プル http://unity3d.com/support/resources/exampleprojects/assetbundles
  123. 123. TIPS (よく使ったUnityの便利機能や小技)
  124. 124. TIPS • 「ExportPackage」は • アセットのリンク関係を • 調べるのに便利。 • シーンを対象にもでき、 • 複数選択もできる。 •フォルダを選べば、 フ ォルダ以下の 全アセッ トからリンクさ • れてる一覧になる。 Assetを選択して 右ク リック-> ExpoertPackage
  125. 125. TIPS アプリのビルドログには、 アプリ内の各アセットの サイズ一覧が出力される。 「Window -> Console ->Open Editor Log」
  126. 126. TIPS デュプリケート:Ctrl+D シーンやプレハブのコピーが簡単にできる。 右クリックメニュー にはない Ctrl+C&Ctrl+Vでは 何も起きない… 応用技~日本語コメントつきのソース作成~ 別エディタでBOMつきUTF16でスクリプト保存 →デュプリケート →中身を全クリア(ただし、文字コードはBOMつきUTF16のまま) →改めてソースを書く Ctrl+Dでコピペ可能!
  127. 127. TIPS ・コマ送り ポーズ後… コマ送り ・スローモーション再生 TimeScaleを1以下に 再生中でも可
  128. 128. TIPS 再生中のシーンからオブジェクトを直接コピー 再生中にコピーして 終了後、 Ctrl+Vすれば再生 中の状態で オブジェクトをコ ピーできる
  129. 129. おしまい

×