こんにちわ、オオバです。

CEDEC2019に聞き手として参加させて頂き「Unityではじめるオープンワールド入門 エンジニア編」セッションを元にDOTS関連についてまとめます。

この記事の内容

そもそもDOTSとは?

簡単に紹介すると、DOTSとは将来のスタンダードなUnity開発手法になると思われるフレームワークです。

これらの技術を使い、実行時のロード高速化、大量のオブジェクト、GC軽減などの恩恵にあずかることが出来ます。

DOTSと既存システムは組み合わせて使用

セッションではオープンワールド風のステージ + キャラ1体という構成のDEMOをベースに技術紹介されています。

オープンワールド風DEMOのざっくり仕様

cedec2019気になったUnity情報DOTS編_0

オープンワールドなので、生い茂った木や草が大量に配置されていて、草は風に揺れている風に動いています。
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

cedec2019気になったUnity情報DOTS編_1

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ボタンを押すだけで更新が入ります。

cedec2019気になったUnity情報DOTS編_2

これで、アーティストとの作業分担はできると思います。

【Unity】Scene上に構築したステージを、Entity群に変換してECSで利用可能にする「SubScene」 - テラシュールブログ
SubSceneについてはこちらの記事をご確認ください。

SubSceneになったことによる良い副作用

4万個のオブジェクト(LOD含めると21万個)をECSを使わなかった場合、実行するだけでもとても時間がかかることが想定されます。理由としては21万個のGameObjectのデシリアライズが入るためです。
エンティティ(SubScene)に事前に変換しておくことで、最適化されたメモリ配列になった状態でオブジェクトがロードされるため高速になります。
比較DEMOでもゲーム実行するまでの時間はECSの方が圧倒的に早かったです。

こういうところがECSの良いところなのでしょう。

現状SubSceneの外部リソース化には難あり

SubSceneに変換したオブジェクトは、以下のディレクトリに格納されます。

それらを外部リソースとして扱うためには、色々と頑張らないといけないようです。
そもそもStreamingAssetsに入っているバイナリはAssetBundleには出来ないので、そのままリモートにアップロードし、Resources配下のファイルはAssetBundleにしてアップロードします。

問題はパスで以下のEntityScenesPathsクラスにベタベタとStreamingAssetsResourcesと書かれているので、この辺を修正してパスを修正する必要がありそうです(未検証)

※確認バージョン 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を使用

cedec2019気になったUnity情報DOTS編_3

PlayerSettingsのGraphicsJobsにチェックを入れます。
するとGPUの処理をRenderThreadに移すことができ、GPU負荷を下げることができます。

CanvasのScreenSpaceOverlay使用しない

CanvasのScreenSpaceOverlayを使用すると毎フレームGPUが動いてしまうため、使用しないことでGPU負荷を下げる、というかGPU負荷を上げないようにしたとのこと。

解像度を下げた

今回実機がiPhoneXなので、DynamicResolutionが対応していたため(Metalは対応している)、解像度を下げてGPU負荷を下げたようです。

その他のトピックス

LightWeight Render Pipelineの名称が変更

Unity2019.3からUniversal Render Pipelineに変更になります。LightWeightという名前がしょぼそうという印象を与えてしまうかららしいです。

cedec2019気になったUnity情報DOTS編_4

最後に

DOTSを実践的に使用したポストモーテム的なセッションで、多くの知見が得られました。
しかし、ECSはこれからもAPIが変わっていきそうな雰囲気がするので、実戦投入はまだまだ先かなという印象です。個人的に遊んでみるのには良いかなと。
また、このオープンワールドのUnityプロジェクトは公開したいと言っていたので、いつかアップされるかもしれません。

オススメ記事