Slide 1

Slide 1 text

Gotanda.unity #7 in 株式会社ミクシィ @渋谷(07/25) 札幌HoloLens ミートアップ vol.2 ~夏編~ LT枠(07/21)

Slide 2

Slide 2 text

自己紹介 mao (@TEST_H_) ・ ゲームプログラマーっぽいフレンズ ・ 多分Qiitaで一番「ドカベンロゴ + ゲーム開発」ネタを  書いている気がする ・ 今回話す内容を含めたXR関連の進捗は全部趣味開発

Slide 3

Slide 3 text

https://twitter.com/i/status/1019018416798162944 OculusGoで大量のドカベンロゴを 60fps近くで動かすデモ。(通称?「ドカベンチマーク」) ※検証作品では最大2万個同時に動かしてる →こちらを実装する上での検証の過程や最適化のコツ?などを   話していければと思います。 今回話すやつ

Slide 4

Slide 4 text

- 実装内容の中にはPreviewな機能も含まれており、 将来的には実装が変わってくる可能性があります。 後はプラットフォームによって挙動が変わることも考慮したり - 今回の実装についても割と手探りなところが多く、 正しいやり方かどうかは不明です。。 故に実装の一例程度に留めて頂けると幸いです。。 - パフォーマンスの結果はUnityのProfiler/FPS表示Script等で測定。 - ※結果についてはあくまで簡易的なものでしか見れていない。 → まだ試せていないがOculus Remote Monitor等で見ると結果が違うかも(要検証) 注意点

Slide 5

Slide 5 text

概要 親子構造での実装 行列演算で最適化 おまけ まとめ 目次

Slide 6

Slide 6 text

概要

Slide 7

Slide 7 text

実装について ・ 仕様 - ドカベンロゴをランダムな位置に配置 + アニメーション + ビル ボードっぽいこと ・ 実装について - Unity2018からの新機能であるJobSystem + ECS + Burst Compilerで実装

Slide 8

Slide 8 text

実装について ・ 前提 - ECSはPureECSで実装 → エントリーポイント/Camera/Canvas以外は   基本的にGameObjectやMonoBehaviourは未使用 - 基本的にどの実装もECS + JobSystemを併用して実装 → ECSだけとかでは無い - 上記に合わせてBurst Compilerも基本的には有効化 → その為、記載している処理速度は有効化した上での数値

Slide 9

Slide 9 text

実装について 今回はLTなので細かい所までは話さない想定です。(時間がが) (多分)詳細な技術情報は以下のQiitaの記事に纏まっているので そちらを参照してみてください。 ※以下のでググると出てくるはず... ・ 【Unity】ドカベンOPのロゴアニメーションをシェーダーで実装してみた ・ 【Unity】ComputeShader + GPU Instancingで大量のドカベンOPのロゴアニメーションを動かしてみた ・ 【Unity】C# JobSystemで大量のドカベンロゴをアニメーションさせてみた ・ 【Unity】ECS + JobSystemで10万個のドカベンロゴをアニメーションさせてみた

Slide 10

Slide 10 text

親子構造での実装

Slide 11

Slide 11 text

親子構造 ・ ドカベンロゴの原点は中央 - ピボットを下端に設定して回す必要があったので一先ずは愚直に親子構造で対応。 子をロゴにして上に少しずらし、親を回転させるアプローチ。 - ↓のイメージはGameObjectだが、ECSでも親子構造の構築は可能。 ※以前「【Unity】PureECSに於けるEntity同士の親子関係の構築方法について」と言う記事を書いたので       実装が気になる方はこちらを御覧ください。 ←実装イメージ こちらをECSで構築している。

Slide 12

Slide 12 text

親子構造 ・ 結果 - 1万個を動かした時点で48〜50fpsな印象。ちょっとゴリラな感じ。 ※計測時のProfilerの負荷も加味して - WorkerThreadに回っている回転処理の負荷だけで重い時で12〜16ms →MainThread側にも処理がまわっており、その時の負荷で大体5~10msの間 - その他にもECSのTransformが持つ親子構造周りと思われる処理でも ちょくちょくと負荷が掛かっている感。(※状況にもよるが0〜3ms以内) まだ調べきれていない点もあるが、 何となく頭打ち感があったので一旦別のアプローチへ。 (後半へ続く)

Slide 13

Slide 13 text

行列演算で最適化

Slide 14

Slide 14 text

行列演算で最適化 ・ 親子構造の廃止 - 何となく負荷が掛かっていた親子構造周りの処理負荷を無くしたい。。 - かと言って既存のTransformのSystem周りを改造するのも大分ゴリラかと思われた。 ・ 新Mathライブラリの負荷?(※回転処理が重い話) - どこで負荷が掛かっている?中身を追う必要がありそう。。 とりあえずは任意点周りの回転行列を算出し、 TransformMatrixに掛け合わせてみることに。 → 別れていた処理を一つのSystemに纏めてみた

Slide 15

Slide 15 text

行列演算で最適化 ・ 動かしてみた - TransformSystem関連の負荷は消えたと言う印象。 - しかし1万個を動かした時点で26〜28fps - 回転行列演算部分について - MainThreadで20〜30ms - WorkerThreadで35〜40ms 結果 : やばたにえん

Slide 16

Slide 16 text

どうしてこうなった ・ 「三角関数、お前だったのか。いつも負荷をくれたのは」 色々調べた結果、回転行列演算時の三角関数で処理負荷が 掛かっている様に見受けられた。 → まさかと思い、「三角関数テーブル」に置き換えて実装してみた所... ※精度はそんなに求められなかったので置き換え自体は問題無いという認識 ※↓の例ではsin/cosともに360度分用意しておりますが、実際にはsin90度分もあれば十分かと思われます。

Slide 17

Slide 17 text

三角関数テーブルで最適化 ・ 結果 - 2万個を動かしても60fps近くをキープできるように(少しブレる) - 回転行列演算部分についてもWorkerThreadで平均1〜3msぐらいに収まり、 重いときでも6msぐらいに。 やはりn万個を同時に動かすとなると、 場合によっては毎回その数分計算→負荷になるかと思われるので、 物によっては事前計算した物に置き換えることで最適化出来そうな気がした。 ※ 別件としてUnite2017に聞いた情報だと三角関数はルックアップテーブル化すると聞いた覚えがある。   今回の検証結果を踏まえての推測だと、恐らくは多分大量に処理する前提のため..?

Slide 18

Slide 18 text

おまけ

Slide 19

Slide 19 text

TransformSystemで負荷を下げつつ回す ・ そもそも親子構造にしなくてもドカベン回転は出来る - SpriteをMesh化する段階で下端を原点に設定できるように頂点を動かした。 →こうする事でECSのRotationだけで回せる。

Slide 20

Slide 20 text

TransformSystemで負荷を下げつつ回す ・ 結果 - 1万個を動かした時点で60fpsに近いぐらい(こちらも少しブレる) - 2万個を動かしたら30fps近くに 結果としては親子構造を使うよりは軽くなった印象。 → 2万個動かした時点で重いのは回転処理の内部で   三角関数が使われているのが原因かと思われる。 ※ 行列演算の最適化前が1万個の時点で重かったのはそもそものロジックが影響していた説... ※ ちなみに頂点を動かした版で軸指定回転行列演算側の計算負荷を下げる検証も念の為試してみたが、   そんなに変わらない印象。

Slide 21

Slide 21 text

まとめ

Slide 22

Slide 22 text

まとめ ・ 大量のオブジェクトを動かすとなると、  それを前提にした設計は必要となってくるかもしれない。 - 今回の例で言えば一部処理のルックアップテーブル化とか。 - 寧ろ前述で小さく書いていたようにライブラリ側で対応される可能性もある。 ・ 今OculusGoが熱い!(物理) ・ どうせ全部描画しないんなら数減らすなりして負荷を下げ(ry ・ JobSystem + ECS + Burst Compilerはいいぞ