つくるの大好き。

つくるのが大好きな人の記録。

DartのStreamのバックグラウンド精度を調べてみた

ここまでのあらすじ

突然のブログ更新を思いたったのですが、久しぶりにも関わらず懲りずに 「Timerの精度」 という全く需要の無さそうな記事を書いてしまいました。

satoshi-maemoto.hatenablog.com

ただ書き始めるとすぐ次のアイディアが浮かんでしまうもので、再び「Streamの精度」というまた需要の無さそうな記事を書いてしまうのでした。

Streamを使用したバックグラウンド処理 その1

定期的な裏タスクを実現する場合、Streamを使用することができます。
Unityでコードを書く人ならばお馴染みの yield ですね。
yieldする際にに呼び出し元にcallbackがされる形で制御が渡り、また制御が戻ってきます。

まず安直なパターンとしてループ内で await Future.delayd(単位待ち時間) として単位待ち時間ごとに制御を返すパターンのテストコードを書きました。

https://github.com/satoshi-maemoto/studying_flutter/blob/e16195369fb0ec6ff7b2e885a6dc1bcbd4e6028a/integration_test/stream_test.dart#L7-L26

  Stream<int> runLoop(
      WidgetTester tester, double desiredFps, int testSeconds) async* {
    var duration = Duration(microseconds: (1000000.0 / desiredFps).truncate());
    var start = DateTime.now();
    tester.printToConsole(
        "START: ${start.toString()} desiredFps:$desiredFps duration:${duration.toString()}");

    var called = 0;
    var end = start.add(Duration(seconds: testSeconds));
    while (DateTime.now().compareTo(end) < 0) {
      ++called;
      await Future.delayed(duration);
      yield called;
    }

    var actualFps =
        called.toDouble() / (end.difference(start).inMicroseconds / 1000000.0);
    tester.printToConsole(
        "END:   ${end.toString()} called:$called difference:${end.difference(start)} actualFps:$actualFps");
  }

これは単位待ち時間分待つので、その他の処理が行われる時間の分だけyield回数が少なくなることは明白ですね。
動かしてみましょう。

  • iPhone 14 Pro
    START: 2023-02-05 19:47:54.229318 desiredFps:60.0 duration:0:00:00.016666
    END: 2023-02-05 19:48:04.229318 called:546 difference:0:00:10.000000 actualFps:54.6

  • Xperia1 II
    START: 2023-02-05 19:26:18.861561 desiredFps:60.0 duration:0:00:00.016666
    END: 2023-02-05 19:26:28.861561 called:535 difference:0:00:10.000000 actualFps:53.5

60回を期待しているところ54回程度の呼び出ししかされない模様。
これは予想通りちょっとダメでしたね。

Streamを使用したバックグラウンド処理 その2

次にループ内ではウェイトせず、単位待ち時間が経過したらyieldするという少し丁寧な処理にしたパターンです。

https://github.com/satoshi-maemoto/studying_flutter/blob/e16195369fb0ec6ff7b2e885a6dc1bcbd4e6028a/integration_test/stream_test.dart#L28-L44

  Stream<int> runLoop2(
      WidgetTester tester, double desiredFps, int testSeconds) async* {
    var duration = Duration(microseconds: (1000000.0 / desiredFps).truncate());
    var start = DateTime.now();
    tester.printToConsole(
        "START: ${start.toString()} desiredFps:$desiredFps duration:${duration.toString()}");

    var called = 0;
    var end = start.add(Duration(seconds: testSeconds));
    var prevCalled = start;
    while (DateTime.now().compareTo(end) < 0) {
      if (DateTime.now().difference(prevCalled) > duration) {
        prevCalled = DateTime.now();
        ++called;
        yield called;
      }
    }

    var actualFps =
        called.toDouble() / (end.difference(start).inMicroseconds / 1000000.0);
    tester.printToConsole(
        "END:   ${end.toString()} called:$called difference:${end.difference(start)} actualFps:$actualFps");
  }

さてどうなるでしょうか、動かしてみましょう。

  • iPhone 14 Pro
    START: 2023-02-05 19:48:06.290216 desiredFps:60.0 duration:0:00:00.016666
    END: 2023-02-05 19:48:16.290216 called:599 difference:0:00:10.000000 actualFps:59.9

  • Xperia1 II
    START: 2023-02-05 19:26:30.947065 desiredFps:60.0 duration:0:00:00.016666
    END: 2023-02-05 19:26:40.947065 called:599 difference:0:00:10.000000 actualFps:59.9

おお、60回を期待しているところにほぼ60回程度の呼び出しが行われました!
この方法が精度としては最も良さそうです。
ループ回数が多いのでCPU使用率= バッテリー消費量という面では若干不安がありますがそちらはまた追って調べてみたいと思っています。

まとめ

というわけでDartのバッググラウンド処理の時間的精度は、TimerよりStreamの方が高いということがわかりました。

Flutterはじめました / DartのTimerの精度を調べてみた

新年あけましておめでとうございます!

Flutter (Dart言語) はじめました

最近はFlutter (Dart言語) を触ることが増えています。
入門して1ヶ月少々の超ビギナーなので、調べてわかったことをメモして行こうかなと思っています。
もっと良い方法をご存知でしたらぜひ教えてください。

Timerの精度を調べるコード

秒間60回程度の頻度でタスクを実行する仕組みが作りたいなと思いました。 こういう場合Dartはシングルスレッドで動作するので、定期的なタスクはTimerで作れば良さそうです。

テストコード
https://github.com/satoshi-maemoto/studying_flutter/blob/main/integration_test/timer_test.dart

tester.printToConsole("=== START ${tester.testDescription} ===");

var desiredFps = 60.0;
var testSeconds = 10;

var duration = Duration(microseconds: (1000000.0 / desiredFps).truncate());
var called = 0;
var start = DateTime.now();
tester.printToConsole(
    "START: ${start.toString()} desiredFps:$desiredFps duration:${duration.toString()}");
var clock = Timer.periodic(duration, (t) {
    ++called;
    //tester.printToConsole(DateTime.now().toString());
});

await Future.delayed(Duration(seconds: testSeconds));

clock.cancel();
var end = DateTime.now();
var actualFps =
    called.toDouble() / (end.difference(start).inMicroseconds / 1000000.0);
tester.printToConsole(
    "END:   ${end.toString()} called:$called difference:${end.difference(start)} actualFps:$actualFps");

1秒間に60回の呼び出しを期待しつつ、10秒後に平均のレートを出力するコードです。

テスト結果

  • iPhone 14 Pro
    START: 2023-02-05 17:53:32.903171 desiredFps:60.0 duration:0:00:00.016666
    END: 2023-02-05 17:53:42.907459 called:625 difference:0:00:10.004288 actualFps:62.47321148691441

  • Xperia1 II
    START: 2023-02-05 17:48:27.789945 desiredFps:60.0 duration:0:00:00.016666
    END: 2023-02-05 17:48:37.796106 called:625 difference:0:00:10.006161 actualFps:62.46151745909345

60回を期待しているところ62.5回の呼び出しがされる模様。
遅いよりは良いけどあんまり正確じゃないなぁ〜。
まあシングルスレッドなので他のところで処理を専有されるとグダグタになることは予想されるな。

まとめ?

というわけでDartのTimerは結構ルーズである模様。
もっと高精度なバックグラウンド処理ができる方法を知っていたらぜひ教えてください。

Sony "ToF AR" SDK サンプル紹介 [3] - Hand, Mesh サンプル

前回はToF ARのPointCloud関連およびSegmentationサンプルを紹介しました。

satoshi-maemoto.hatenablog.com

今回は ToF ARで最も強力な機能と思われる、高精度なHand認識機能のサンプルからご紹介してゆきましょう。
ToF ARの手認識精度、凄いです。

Hand

youtu.be

Handシーンは手の認識結果を表示できるサンプルです。

TofArHandコンポーネントの機能

HandデータはTofArHandコンポーネントから取得することができます。少し詳しく見てみましょう。
取得できる情報は下記のとおりです。

  • 手の位置(3D座標)
  • 手の関節位置(3D座標)
  • 手のポーズとジェスチャー
  • 指が平面をタッチしているか

リアカメラ、フロントカメラ共に使用できるので自分以外の人を映す、自撮りで使う、という両方の用途に使うことができます。
ただし手認識を行えるカメラは密度の高いDepthデータが取得できるToFカメラである必要があります。
iOSバイスはフロントにTrueDepthカメラが搭載されていて密度の高いDepthデータが取得できます。
対するAndroidはリアカメラで密度の高いDepthデータが取得できるデバイスは多いもののフロントにToFカメラを搭載しているデバイスは少ないようです。

詳しくはこのリストを見ると、どのカメラでToFデータが取得できるのかわかります。 https://developer.sony.com/develop/tof-ar/development-guides/docs/ToF_AR_User_Manual_ja.html#_%E5%90%8C%E6%99%82%E8%B5%B7%E5%8B%95%E5%8F%AF%E8%83%BD%E3%81%AAcolordepth%E3%82%AB%E3%83%A1%E3%83%A9%E3%81%AEid%E3%81%A8%E5%90%91%E3%81%8D

認識できる指関節数は25点。Leap Motionの代わりに使うことができそうです。

https://static.developer.sony.com/develop/tof-ar/development-guides/docs/images/tofar_220315_hand_handindex.png?t=1655898625742

ポーズとは手の瞬間的な形で、今この瞬間ピースサインをしているとか、サムアップしているという情報です。
ジェスチャーとは一定時間内の連続的な手の動きのパターンから識別される動作です。
かなりたくさんの種類が用意されていますね。

Enum PoseIndex

Enum GestureIndex

その他詳しくは下記のページをご覧になってみてください。
https://developer.sony.com/develop/tof-ar/development-guides/docs/ToF_AR_Reference_Articles_ja.html#_hand_component

圧巻の認識精度

認識精度についてはもうこの動画にあるように説明不要で圧巻という感じ!
ToF ARを使うだけで手持ちのスマホLeap Motionが搭載されると考えるとお得感がありますね〜。

youtu.be

そしてこのToF ARの高精度なHand認識機能は「バーチャルシンデレラプロジェクト」の配信でも使われてゆくようです。 virtual-cinderella.jp

B向けの領域でも簡単即座に人の所作を記録して再現することができるので、職人さんの技能伝承であったり3Dマニュアル作成などでも使えそうですね!

Live Mesh Occlusion

youtu.be

Live Mesh OcclusionシーンはToFデータからリアルタイムに3D Meshを生成し、それを用いて現実とCGのオクルージョン表示を行うサンプルです。

3D Mesh生成についてはTofArMeshコンポーネントからMeshの頂点データを取得でき、DynamicMesh Prefabが表示を行なってくれるため難しい処理を自分で書く必要な無さそうです。
そして3D Meshなので影を作る、影を受けることもできリアルなAR表現に役立ちますね。

https://developer.sony.com/develop/tof-ar/development-guides/docs/ToF_AR_Reference_Articles_ja.html#_mesh_component

オクルージョン表示というともう7年も前ですが趣味で積極的に作っていて、当時はKINECT V2を使って色々とデモ動画を出していました。

youtu.be

これは3D Mesh化は行なっていないのですが、ShaderでToFデータの深度情報とCGのZ-Buffer値を比較し、Color映像と合成することで低い処理負荷でぬるぬる表示ができていたのが特徴です。
詳しい方にはこれは凄いとかなりの高評価を頂くことができましたね。
反面、一般の方から見ると 「自然な表示になった → 不具合が直って当たり前の表示になった」 くらいの印象だったのが面白いというか残念でしたね(笑)
しかし裏を返すとオクルージョンの無いAR表示は一般の方にとって不具合レベルであるということでもあります。
オクルージョン重要ですね〜。

Color Hand Occlusion

youtu.be

Color Hand Occlusionシーンは手の周辺だけリアルタイムオクルージョン表示を行うサンプルです。
Handシーンの機能とLive Mesh Occlusionシーンの機能を組み合わせたものになります。

これはどんな応用ができるかな。。
手だけが見えるリアルタイム仮想背景表示ができるので、手話ビデオを作ったり指人形劇の配信などできるかな(発想力の貧しさ)

まとめ

今回はToF ARの最も特徴的な機能であるHand認識機能を軸にご紹介しました。
手持ちのスマホが即座に高い認識精度のモーションキャプチャバイスになり、スマホなのでそのままネットワークに配信できる、ということを活かすと新しい面白いものが実現できそうですね!

Sony "ToF AR" SDK サンプル紹介 [2] - PointCloud, Segmentation サンプル

前回はToF ARとは何か、そしてToF ARの根幹をなすカメラ映像、ToFデータといった基本データ表示関連のサンプルを紹介しました。

satoshi-maemoto.hatenablog.com

引き続き、基本データから2次処理で生成・認識されるデータを確認できるサンプルを紹介してゆきますね。

Point Cloud

www.youtube.com

Point Cloudシーンは3D点群データを表示できるサンプルです。
Point CloudデータはToFコンポーネントから簡単に取得することができるので、ToFデータから自分で変換して作るような面倒な処理は不要で助かりますね。

データ形式の詳細はリファレンスの "2.1.3. データ形式: PointCloudデータ" に載っています。
https://developer.sony.com/develop/tof-ar/development-guides/docs/ToF_AR_Reference_Articles_ja.html#_tof_component

Point Cloudサンプルは、点群表示を拡大縮小、回転させることができます。 自分の姿を横から見たりすると3Dでデータを取れているんだっていうことが分かりやすく感じられて面白いですよね!

PointCloud

僕と点群の出会いはもう10年以上前ですかね、 僕は中田ヤスタカさんのCAPSULE の曲が好きなのですが、PVで中田ヤスタカさんが細かい粒子になってソフトクリームみたいになりつつ回っていくと言う表現がよく使われており、めちゃくちゃかっこいいなーと思ったのが初めてのような気がします。
深夜にライブに行くことも多かったのですが、ライゾマティクスの真鍋大渡さんがVJをやった回ではKINECTの王様みたいな大きなセンサーを置いてリアルタイムポイントクラウドエフェクトをぐりぐり回していたのを覚えています。
今だったら、スマホ一つで点群を取得してShaderでいい感じに料理してあげることで超かっこいいエフェクトがリアルタイムに作れるんじゃないでしょうか。

Colored Point Cloud

youtu.be

Colored Point CloudシーンはRGBデータも交えて色付きの3D点群データを表示できるサンプルです。

ソースを見てみると、ToFデータとRGBデータのマッチングをとるTofArCoordinateManagerが処理を簡単にしてくれているようです。
https://github.com/SonySemiconductorSolutions/tof-ar-samples-basic/blob/f4865d44230eda2ebde634b5bbfd796314d37c04/Assets/TofArSamplesBasic/ColoredPointCloud/Scripts/ColoredPointCloud.cs#L83-L90

ToFカメラとRGBカメラは解像度や視野角が異なりますし、端末上の物理的な取り付け位置も異なるのでカメラ単体で撮影した映像を単純に重ね合わせるだけではずれが生じます。
そこを合わせるにはカメラごとの特性を表すパラメータを元に計算を行う必要があります。

詳しくはこのようなスライドがあるようなのでよかったらぜひご覧ください。

カメラパラメータは機種はもちろん、同じ機種でもモデルのよって異なることがあるので、その違いを吸収してくれるものがサクッと数行で使えるというのはすごいことだと思います!

Human Point Cloud

youtu.be

Human Point CloudシーンはRGBデータに加え、ToF AR のSegmentationコンポーネントの認識結果も交えてRGB映像上の人物(と推定される部分)のみに限定した色付きの3D点群データを表示できるサンプルです。

Segmentationコンポーネントの人物認識についてはこちらに説明が書かれていますが、Human Depthもあるようなので、ARFoundationではiOSバイス上でしかできなかった Human Stencil, Human Depth がAndroidでも使えるということですね! https://developer.sony.com/develop/tof-ar/development-guides/docs/ToF_AR_Reference_Articles_ja.html#_humandetector

このあたりで人物のマスクデータを取っていることが分かりますね。 https://github.com/SonySemiconductorSolutions/tof-ar-samples-basic/blob/f4865d44230eda2ebde634b5bbfd796314d37c04/Assets/TofArSamplesBasic/HumanPointCloud/Scripts/HumanPointCloud.cs#L308-L317

Segmentation

youtu.be

SegmentationシーンはToF AR のSegmentationコンポーネントの認識結果を表示するサンプルです。現在は以下2つの認識機能が用意されています。

  1. SkyDetector - 空(そら)部分を認識し、該当部分のマスクデータを取得できる
    https://developer.sony.com/develop/tof-ar/development-guides/docs/ToF_AR_Reference_Articles_ja.html#_skydetector
  2. HumanDetector - 人物部分を認識し、該当部分のマスクデータやDepthデータを取得できる
    https://developer.sony.com/develop/tof-ar/development-guides/docs/ToF_AR_Reference_Articles_ja.html#_humandetector

また、サンプルの設定パネルを見ると、それぞれNot版があり、空(そら)以外をマスクしたり、人物以外をマスクするオプションも用意されています。

Segmentation Options

これらを応用すれば、映像の中で人物だけを消したり、逆にグリーンバックなしのリアルタイム背景差し替え表示なんかも作れそうですね!

まとめ

今回はPoint CloudとSegmentation関係をご紹介しました。
自分で作るとすると大変面倒な処理がAPI化されていたり、iOSではできるがAndroidではできなかったARに役立つ機能が補完実装されていて機種に依存しない開発が行えるようになっていることがわかりました。
次回はいよいよToF ARのユニークかつ強力な機能であるHand機能を紹介していきますのでお楽しみに!

Sony "ToF AR" SDK サンプル紹介 [1] ToF ARとは?Color/ToF映像を表示するサンプル群

久しぶりのブログ執筆です〜。
2022年6月15日にSonyから面白そうなUnity用SDK "ToF AR" が一般公開され、サンプルを色々触ってみましたので紹介して行きたいと思います。

ToF ARとは?

ToF ARとは、、こちらのプレスをご覧ください。 www.sony-semicon.co.jp

要するにSonyが世界的に大きなシェアを持つスマホ用ToFセンサー、LiDARスキャナーのデータや、Sonyが得意とするセンシング技術からもたらされる認識結果データに簡単にアクセスできるUnity用SDK、それが"ToF AR"ということでしょう。
僕が触ってみた所感では、ARアプリが開発できる、というのはもちろん、カメラや画像認識技術へのこだわりが感じられるAPIセットだと思いました。
これがSonyらしいって言うのでしょうか!?

ToF ARのダウンロード

ToF AR はSony Developer World からダウンロードすることができます。

Overview - ToF AR - Sony Developer World

ToF ARに関するツイートを観測しているとライセンス条項が見つけにくいという話があるようですが、ダウンロード時に表示されるので確認しておきましょう。
ダウンロードしたzipファイルを展開すると、SDKのunitypackageが5つ入っています。

ファイル名 説明
ToFAR_Base_v#.#.#_Android.unitypackage Androidビルド用基本機能
ToFAR_Hand_v#.#.#_Android.unitypackage Androidビルド用Handその他の機能
ToFAR_Base_v#.#.#_Android.unitypackage iOSビルド用基本機能
ToFAR_Base_v#.#.#_Android.unitypackage iOSビルド用基本Handその他の機能
TofAR.ThirdParty.ARFoundationConnector-v#.#.#.unitypackage ARFoundation接続機能

細分化されていますが、Android / iOS 両プラットフォーム向けにビルドするのであれば上の4つを全てインポートすれば良いです。
アプリを使用するプラットフォームや必要な機能が限定されている場合はアセットを少なくしてバイナリサイズを小さくできるような配慮かもしれません。

ToF AR Samples Basic サンプルのビルド

ToF ARの基本的な機能を確認できるサンプルは下記GitHubリポジトリから取得することができます。

github.com

クローン、またはzipファイルでダウンロードしたら早速Unity Editorで開いて行きましょう。
動作確認されているUnityのバージョンは、ToF AR v1.0.0 の場合下記です。

  • Unity 2020.3.28f1
  • Unity 2021.2.11f1

Unity Editorでプロジェクトを開くと、エラーメッセージが表示されます。
でもこれはToF AR自体がサンプルのプロジェクトに含まれていないだけなので、慌てず騒がず [Enter Safe Mode] または [ignore] で進みましょう。

プロジェクトオープン時エラー

プロジェクトがオープンできたら、ToF ARのunitypackageをインポートすればビルドエラーは全て解消します。
あとはビルドしてデバイスにデプロイしましょう!

アプリケーションが起動すると、メニュー画面が表示されます。
ひとつひとつのボタンがサンプルシーンになっています。
サンプルシーンからメニューに戻るには画面を4本指でタップします。

Menu

ここからサンプルシーンをひとつひとつご紹介して行きましょう。

Color シーン

イメージしやすいようにビデオを用意しました。 4つの端末でシーンを比較するします。

使用した端末は以下です。

端末名 特徴
Sony Xperia1 II RearにiToFセンサー搭載
Samsung Galaxy S20 Ultra 5G RearにiToFセンサー搭載、高解像度ToFあり
Apple iPhone12 Pro RearにdToF(LiDAR)センサー、Frontに TrueDepthセンサーあり
Apple iPad Pro 12.9inch gen5 大きなiPhone

www.youtube.com

Colorシーンは、RGBカメラの映像を表示するサンプルです。 まあこれくらいなら通常はUnityのWebCamTextureを使えば十分かも知れません。
こだわりポイントはこの圧巻の設定項目です。

Color設定

FPS変更やフォーカス制御、露出の設定、フラッシュの制御などなど。
カメラについてできそうなことは全部できる勢いの設定項目。
データの出力フォーマットもYUVだけでなく、RGBA, BGR, RGB といかにもOpenCVやTensorFlowなどでどうぞComputer Visionやってくださいと言わんばかりです。
そして実はこのColor機能はToFやLiDARを搭載していない機種でも使用することができるので、凝ったカメラアプリなど簡単に作れそうです。

いやあ、いきなりToFでもARでもないところで凄いこだわりを見た感じです。

Color Depth

www.youtube.com

Color DepthシーンはRGBカメラ映像とToFデータ映像を重ね合わせて表示するサンプルです。
ToFカメラについても、Colorカメラほどではありませんが設定が用意されています。

ToF設定

面白いのは Deley設定で、Color映像に対して遅延を起こすことができます。

https://youtu.be/tMWotQi9xl0?t=30

グラディウスのオプション(古)やスタンドのような分身がついてくるようなビジュアル表現が簡単に作れそうです。
ToFデータを遅延させれば、ToFから生成・認識されるHand認識結果やMeshデータなども同じように遅延するので、Color映像で自分の手が通過した後遅れて波紋が出てくるような表現など、色々思いつくところがありますね。誰か作ってくださいw

Basic Stream

www.youtube.com

Basic Streamシーンは、Color, ToF そして Confidence映像を並べて表示するサンプルです。
KINECTを触る人であればConfideneはIRということで大体合ってるのかなと思います。

Galaxy S20 Ultra 5G では 640x480 高解像ToFモードが用意されています。
https://youtu.be/Zla6JZKEafM?t=62
高解像な代わりにFPSが5程度に落ちるのですが、Androidで静的な物体に対して密度の濃いDepthデータが欲しい場合使いでがあるモードではないかと思います。
対するiOSバイスではFrontで高解像高密度のDepthデータが15FPSで取得できます。
いずれにしても解像度が高まるとFPSが落ちる、無理をさせると熱が出る。
魔法って無いんだなって思いますよね。

Depth Confidence

www.youtube.com

Depth Confidenceシーンは、ToFとConfidenceを表示するサンプルです。
このシーンの特色は、Depth映像上のタップした部分の距離情報を表示してくれるところです。
簡易メジャーとして使えます。

逆にこのToFカメラ本当に正確なの?っていうのを壁から正確に1メートルのところから壁までの距離を表示させて精度を測る、みたいな使い方もできますけど普通あんまりそういうことはしないですかね。僕はよくやりますけど(笑)

まとめ

今回はここまで。
サンプルを動かしてみてその特徴や思うところを徒然なるままに書いてみました。
カメラにフォーカスしたSDKであることが感じていただけたでしょうか。
引き続き残りのサンプルを紹介していきますので次回もお楽しみに!

次回はこちら
satoshi-maemoto.hatenablog.com

MacBook Pro (M1 Pro)のUnity Android Build ベンチマーク

お久しぶりです!
MacBook Pro 16-inch が届きました!CPUはM1 Proを選択しています。
とにかく物凄い性能だと言われていますが自分がよく使うユースケースでどれくらい凄いのかベンチマークを取ってみました。

f:id:peugeot-106-s16:20211101131246j:plain
MacBook Pro 16-inch

1.ユースケース

僕は普段Android / iOS用のライブラリやSDK、ツールの設計開発を行なっています。
開発言語はC++(Android Studio, Xcode)とUnityです。
カメラ系のものなので基本的に低レイヤのC++実装部で処理を行ない、高レイヤのUnityとやり取りをします。
動作確認は基本的にはUnityでビルドを行ない、実機へアプリを転送して行うことになります。 そのビルド時間はだいたい5分ぐらいの印象です。

この 5分というのはその間に他のことをするには短いけれど待つには長い です。

絶妙にどうしようもない時間です(笑)
僕の場合、チームからプルリクエストが送られてくるのでソースコードレビューをすると共に、動かしてみないとわからない変更については都度チェックアウトしてプロジェクトを開き、ビルドして動作確認をします。
その度にビルド5分です。
動かした瞬間うまく動かなかったりしたらそのビルドは無駄になり、フィードバックして直ったと連絡を受けるとまたビルドです。
仕事時間の大半がUnityビルドに費やされると言っても過言ではない日があるので
1分1秒でもビルドは短くしたい のです。
僕は限りある人生の時間をもっと有効に使いたいんです!

それで今回は UnityプロジェクトをオープンしてAndroidアプリをビルドする というユースケースベンチマークを取ってみたいと思います。

サンプルに使用するUnityプロジェクトはこちら。

github.com

2.比較環境

A: G-Tune (NG-N-i5750) B: MacBook Pro (13-inch, 2020) C: MacBook Pro (16-inch, 2021)
CPU Core i7-9750H 2.60GHz M1 M1 Pro
Memory 32GB 16GB 32GB
Storage SSD SSD SSD
OS Windows 11 Pro 21H2 macOS Monterey 12.0.1 macOS Monterey 12.0.1
価格 約30万円 約20万円 約40万円

マウスコンピュータのG-Tune ゲーミングノートをベンチマークの基準としました。これは約2年前に購入ししたものです。
MacBook Pro はM1 Proの機体に加えM1を搭載した13-inch も用意しました。M1 Proになるとどれだけ性能か変わるか楽しみですね!!

3.比較結果

というわけで、結果どん!
かかった時間に加え、基準であるG-Tune対して削減された秒数、高速化率を求めています。
また、同じようにM1に対してM1 Proで削減された秒数、高速化率も求めています。
(なお処理時間計測はストップウォッチで行なっているため若干の誤差はあります。)

f:id:peugeot-106-s16:20211101141313p:plain
比較結果

実行したアクションの流れは下記です。

  • Libraryフォルダなどのテンポラリフォルダを削除した状態でプロジェクトを開く x 3回
  • ビルドプラットフォームをAndroidに切り替える
  • ビルドする(インクリメンタルビルドが有効なので、初回と2-5回目の平均を分けて求める)
  • Unityのバージョンを変更してビルドする(初回と2-5回目の平均を別に求める)

4.考察

4-1.Unity2020からUnity2021に移行すると

  • 初回ビルドは、M1 Pro(C)以外は2020のほうが速い。インクリメンタルビルドの準備に時間がかかるのかも。
  • 2回目以降のビルドは物凄く速くなる。所要時間は半分程度になる。

同一プロジェクトを繰り返しビルドすることが多い人はUnity2021を使えばそれだけで働き方改革ができる!

4-2.G-Tune(A)からM1(B)に移行すると

  • Unity Projectオープンは133%の高速化
  • 初回ビルドは160%の高速化
  • 2回目以降のビルドは125-145%の高速化

30万円のPCから20万円のPCへ乗り換えて総じて150%近くの時間短縮ができる。なんで乗り換えないの!?レベル

4-3.G-Tune(A)からM1 Pro(C)に移行すると

  • Unity Projectオープンは161%の高速化
  • 初回ビルドは165-172%の高速化
  • 2回目以降のビルドは130-149%の高速化

30万円のPCから40万円のPCへ乗り換えて総じて160%近くの時間短縮ができる。凄い!凄いけど投資もそれなりだよね!

4-4.M1(B)からM1 Pro(C)に移行すると

  • Unity Projectオープンは141%の高速化
  • 初回ビルドは114-129%の高速化
  • 2回目以降のビルドは107%の高速化

プロジェクトを開いてからの初回ビルドは速くなった!けどビルドはそんなに変わらん?

5.まとめ

以上ベンチマーク結果をまとめると、僕のユースケースにプロジェクトオープンと初回ビルドが高速化されるM1 Pro 搭載 MacBook Pro はベストマッチだということがわかりました!

ただ正直多くのUnityでビルドする方が M1 から M1 Pro / Max に乗り換えるほどでもない ということも見えました。
ただ今回はUnity以外のアプリは終了させたクリーンな環境でテストしたので、ブラウザで多くのタブが開き、Android StudioXcodeなどの別のツールを立ち上げメモリを消費した状態ではもっと大きな差が出そうです。
実際、ビルド以外の普通の操作のキビキビ感はM1 Pro の恩恵だなと感じています。

現在非M1のPCをお使いの方はM1に乗り換えない理由は無いと思いました。

うまくて速くて安いからです

また驚くべき事実として、まだUnityやそこから呼ばれるJava, GradleなどのツールはM1に最適化されていません。
追って最適化が行われるとまた劇的に速くなると期待できます。これはやばい(語彙).

f:id:peugeot-106-s16:20211101174602p:plain.

M1 Pro / M1 Max 搭載のMacBook Proについてはベンチマーク記事がたくさん出ていますが自分が実用するユースケースとは乖離があるので自分で調べてみるとさまざまな気づきがありました。
また、Unityでデバイス向けIL2CPPビルドを多く行う方にとっても参考にしてもらえる情報になるのではないかと思います。

さて、じゃあ節約できるようになった時間でどれだけコストが減るのかというお金面はあまり触れていません。
次回、じゃあ乗り換えると何円お得なの!?っていうのを計算して記事を書く予定です。

Azure Spatial Anchors のすぐビルドできるプロジェクト

f:id:peugeot-106-s16:20201206115603p:plain

What's?

Azure Spatial Anchors の勉強をしたのですが、チュートリアルをなぞってビルドしてゆくにはそれなりに時間がかかって大変でした(笑)
すぐビルドできるプロジェクトを公開したので良かったらお使いください。

下記が特徴です。

  • アカウント情報を設定すればすぐビルドできます。
  • UWP(Windows Mixed Reality), Android with ARCore, iOS with ARKit の3プラットフォームに対し、プラットフォーム切り替えだけでビルドでき、動作します
  • Coarse Relocalizationに対応しています
    (うまく動かせていないプラットフォームもあります。リポジトリのReadmeを参照ください)
  • 操作がシンプルなので、営業してくれる人に渡すデモアプリ等に使うと便利です(生々しいw)

github.com

Demo videos

参考リンク

宮浦さん、ありがとうございます! qiita.com