こんにちは、エンジニアのオオバです。
CEDEC2019に聞き手として参加させて頂き「Unityではじめるオープンワールド入門 エンジニア編」セッションを元にDOTS関連についてまとめます。
→11万文字で徹底解説した「DOTweenの教科書」Unityアニメーションの超効率化ツールはこちら
そもそもDOTSとは?
簡単に紹介すると、DOTSとは将来のスタンダードなUnity開発手法になると思われるフレームワークです。
- NativeContainer
- Entitiy Compmnent System(以下:ECS)
- C#JobSystem
- Burst Compiler
これらの技術を使い、実行時のロード高速化、大量のオブジェクト、GC軽減などの恩恵にあずかることが出来ます。
DOTSと既存システムは組み合わせて使用
セッションではオープンワールド風のステージ + キャラ1体という構成のDEMOをベースに技術紹介されています。
オープンワールド風DEMOのざっくり仕様
- 1km四方のステージ
- 主にTerrainで作成(その他Houdini、Maya、SubStance Designerを使用)
- 4万オブジェクト(LOD含めると21万オブジェクト)
- 全体で1200万ポリゴン
オープンワールドなので、生い茂った木や草が大量に配置されていて、草は風に揺れている風に動いています。
21万個のGameObjectを動かすというのはまず無理なので、それをDOTSだったらグリグリ動かせる、またモバイルでも動きますよというDEMO担っています。実機のiPhoneXでも30FPS出ていました。
DOTSは草や木のみ使用
オブジェクト | タイプ | |
---|---|---|
草・木 | エンティティ | |
キャラ | GameObject |
ということで、全てのオブジェクトがECSということではなく、適材適所で使用されていました。
エンティティとは、ECSの世界で言うGameObject的なものでGameObjectから機能をそぎ取ったものです。
ECSを少しでも触ったことがある人ならわかると思いますが、現状のUnityエディタにおけるECSの扱い方はとてもハードモードでして、現状のGameObjectベースの開発と比べると、Unity社が掲げている思想「ゲームを民主化する」には程遠い状態です。
ということで、たくさん配置するものはECS、それ以外はGameObjectで作るというのが、現状の選択肢になるのではないかと思います。
シーンビューを活用したECSワークフロー
Unityの良いところの1つはエディタが強力な点です。
ECSで開発するときもエディタのシーンビューを使って、画面を見ながら開発したいため(その方が作りやすい)、SubSceneを使用したワークフローの紹介がされていました。
GameObjectをエンティティに変換したSubScene
Hierarchyから任意のGameObjectを選んでコンテキストメニューからNew SubScene From Selection
をクリックするだけでGameObjectはエンティティに変換されます。
4万個のオブジェクトを一つ一つSubSceneにするわけにはいかないので、ステージを4分割し、4つのSubSceneを作成しています。
4分割の理由はTerrainを4つ使っているので、その単位でSubSceneにしているようでした。
ちなみにSubSceneに変換すると変換前のGameObjectは、変換したSubSceneの子階層に入ります。
SubSceneに変換したGameObjectに更新が入った場合のワークフロー
SubSceneに変換したGameObjectに更新が入った場合は、元のGameObjectを修正してSubSceneのInspectorのRebuild Entity Cache
ボタンを押すだけで更新が入ります。
これで、アーティストとの作業分担はできると思います。
【Unity】Scene上に構築したステージを、Entity群に変換してECSで利用可能にする「SubScene」 - テラシュールブログ
SubSceneについてはこちらの記事をご確認ください。
SubSceneになったことによる良い副作用
4万個のオブジェクト(LOD含めると21万個)をECSを使わなかった場合、実行するだけでもとても時間がかかることが想定されます。理由としては21万個のGameObjectのデシリアライズが入るためです。
エンティティ(SubScene)に事前に変換しておくことで、最適化されたメモリ配列になった状態でオブジェクトがロードされるため高速になります。
比較DEMOでもゲーム実行するまでの時間はECSの方が圧倒的に早かったです。
こういうところがECSの良いところなのでしょう。
現状SubSceneの外部リソース化には難あり
SubSceneに変換したオブジェクトは、以下のディレクトリに格納されます。
- Assets/EntityCache/Resources/
- Assets/StreamingAssets/EntityCache/
それらを外部リソースとして扱うためには、色々と頑張らないといけないようです。
そもそもStreamingAssetsに入っているバイナリはAssetBundleには出来ないので、そのままリモートにアップロードし、Resources配下のファイルはAssetBundleにしてアップロードします。
問題はパスで以下のEntityScenesPathsクラスにベタベタとStreamingAssets
、Resources
と書かれているので、この辺を修正してパスを修正する必要がありそうです(未検証)
※確認バージョン Entity v0.1.1 preview
public static string GetLoadPath(Hash128 sceneGUID, PathType type, int sectionIndex)
{
if (type == PathType.EntitiesSharedComponents)
return $"{sceneGUID}_{sectionIndex}_shared";
else if (type == PathType.EntitiesHeader)
return GetPath(sceneGUID, type, "");
var path = GetPath(sceneGUID, type, sectionIndex.ToString());
if (type == PathType.EntitiesBinary)
return Application.streamingAssetsPath + "/EntityCache/" + Path.GetFileName(path);
else if (type == PathType.EntitiesSharedComponents)
return Path.GetFileNameWithoutExtension(path);
else
return path;
}
まだまだPreviewなので、変更されるかもしれません。
端末が熱くならないようにGPU負荷を下げるTips
経緯としてはiPhoneXで動かしたら実機が異常に熱くなり、CEDEC会場で展示するということも踏まえ対策をされたようです。
プロファイルするとGPUに異常な負荷がかかっていたとのことで、以下それを解消するためのTipsです。
VertexShaderがクソ重い問題
VertexShaderが72ms使用していたようで、原因は草などに使用されているカットアウトでした。
ということで、カットアウトをやめるという修正を入れました。モバイルとは相性が悪いカットアウトです。
OnDemandRendering.renderFrameIntervalで描画処理をスキップ
cedec2019気になったUnity情報パフォーマンス編
ここでも取り上げたOnDemandRendering.renderFrameInterval
が活躍しています。
実機は展示されるため、触っていないときには負荷を下げて端末の熱が上がらないようにしたいところ。そこでOnDemandRendering.renderFrameInterval
を使い、画面に指がタッチしていないときには描画処理をスキップさせて負荷を下げ、無駄な発熱を抑えることが出来たようです。
Graphics Jobsを使用
PlayerSettingsのGraphicsJobsにチェックを入れます。
するとGPUの処理をRenderThreadに移すことができ、GPU負荷を下げることができます。
CanvasのScreenSpaceOverlay使用しない
CanvasのScreenSpaceOverlayを使用すると毎フレームGPUが動いてしまうため、使用しないことでGPU負荷を下げる、というかGPU負荷を上げないようにしたとのこと。
解像度を下げた
今回実機がiPhoneXなので、DynamicResolutionが対応していたため(Metalは対応している)、解像度を下げてGPU負荷を下げたようです。
その他のトピックス
- SRPBatcherとは相性悪し
- TerrainToolが良さげ。複数のTerrainをつなげることができる。今回だと4つ使用。つなぎ目はわからないくらい馴染んでいる
- キャラの落ち影はリアルタイム
- GPU Instancingではライトマップが使えない
- HLODを使用
- LODはGitHub - Whinarn/UnityMeshSimplifier: Mesh simplification for Unity.を使用
- 草の描画はAmplify Impostors | Utilities Tools | Unity Asset Storeを使用してビルボードで描画
LightWeight Render Pipelineの名称が変更
Unity2019.3からUniversal Render Pipelineに変更になります。LightWeightという名前がしょぼそうという印象を与えてしまうかららしいです。
最後に
DOTSを実践的に使用したポストモーテム的なセッションで、多くの知見が得られました。
しかし、ECSはこれからもAPIが変わっていきそうな雰囲気がするので、実戦投入はまだまだ先かなという印象です。個人的に遊んでみるのには良いかなと。
また、このオープンワールドのUnityプロジェクトは公開したいと言っていたので、いつかアップされるかもしれません。
この記事が気に入ったらフォローしよう