Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ARでVRアバターを表示するシステムを構築しよう

 ARでVRアバターを表示するシステムを構築しよう

次の講演資料です。
・どっかんナゴヤ'18 Jun. https://dcn.connpass.com/event/87240/
・ABC 2018 Spring https://abc.android-group.jp/2018s/

プロジェクトファイル
https://github.com/TORISOUP/AR_VR_Viewer

torisoup

June 09, 2018
Tweet

More Decks by torisoup

Other Decks in Technology

Transcript

  1. ARでVRアバターを 表示するシステムを 構築しよう 2018/06/09 とりすーぷ

  2. 自己紹介 • とりすーぷ • @toRisouP • 個人ゲーム開発者 • 日本Androidの会Unity部 部員のはず

  3. 過去作 • ハクレイフリーマーケット • Unity製、PC向け東方2次創作ゲーム、ネットワーク対戦対応 • 発売中!

  4. 今回の発表概要

  5. こういうものを作ってみた 相手:みゅみゅ(@miyumiyuna5)さん https://twitter.com/toRisouP/status/996761692456435712

  6. これなに? • VR空間のアバターをARで表示するシステム • スマホだけでVR空間をそれっぽく見たい • VR側での演者の動きをそのままARで表示する • 通話機能で会話できる •

    ARカメラの位置をVR側から視認できる
  7. できること • VR側 • アバターの操作 • 表情変更 • AR側カメラがどこにあるかを知る •

    AR側 • マーカーレスで認識した平面にアバターを配置 • アバターのサイズ変更
  8. コンセプト • 「次世代のVR生放送がこんな感じになるといいな」 • VR空間をスマホさえあれば見られるようにしたい • AR側からVR側へのインタラクションもできるといいな • 簡略化のために1対1の通信で作るが、最終的には多対多にしたい

  9. つまり? • こういう美少女空間をスマホARでみたい 画像引用:https://www.infiniteloop.co.jp/blog/2018/04/virtualcast-release/

  10. Unityプロジェクト • githubで公開済み • https://github.com/TORISOUP/AR_VR_Viewer • CC0 で公開

  11. 今回の発表内容 • どうやって作ったか?のノウハウ共有 • 構成 • ワークフロー • VRMの使い方 •

    ネットワーク同期の話 • VR/ARの実装 • その他実装のコツ
  12. 構成

  13. 全体図 VR側 AR側 ・コントローラ入力 ・アバターの姿勢・座標 ・音声 ・ARカメラの位置 ・音声

  14. プロジェクト構成 • 1つのプロジェクトでAR/VRの両方をビルドする • 同じプロジェクトから両パターンビルドできるようにする • 単にプロジェクトを分けるのが面倒くさかっただけ…

  15. 使ったもの(機材) • VR側 • Windows PC • HTC Vive •

    AR側 • Galaxy S8
  16. 使ったもの(ソフト) • Unity 2018.1 / .NET 4.6 / C#6.0 •

    VRM / UniVRM • ARCore • SteamVR、Final IK • Photon Cloud, Photon Voice • UniRx, PhotonRx • Zenject
  17. Unity 2018.1 • .NET 4.6 /C#6.0の開発がどれくらい楽か検証したいので採用 • async/awaitを使いたい

  18. VRM • VRアプリケーション向け人型3Dアバターフォーマット • オープンソースで様々なプラットフォームで利用可能 • 利用ライセンスをファイル自体に埋め込める • 今回はVRMのUnity向けインポータ「UniVRM」も使用

  19. ARCore • Google製のARライブラリ • Tangoの後継 • マーカ検知、マーカレストラッキング、床・壁の検知、光源推測、特 徴点抽出、認識した空間の共有 • 利用可能端末がかなり少ない(アップデートで追加はされている)

    • 今回の利用バージョンは1.2.0
  20. SteamVR • Valve社が提供するVRプラットフォーム & SDK • PC向けVR開発に利用可能なSDK

  21. Photon Cloud/Voice • Photon Cloud • ドイツのExit Games社製の通信フレームワーク&クラウドサーバ • 20人同時接続までなら無料で利用可能

    • Unity向けSDK(PUN)を利用して開発する • Photon Voice • Photon Cloudと連動して音声通信機能を追加するサービス
  22. その他 • UniRx • Reactive Exntensions for Unity • イベント処理、非同期処理の整備に使った

    • Zenject • 依存性注入(DI)のフレームワーク • コンポーネントの参照解決に使った
  23. 開発方針 • 「モダンな開発をしたい」 • .NET 4.6 + C# 6.0 で開発

    • 全体的に挙動を非同期にする(Task, Observable, async/awaitの活用) • DIをメインに使った開発 • static変数を使った参照解決をしない • GameObject.Find禁止
  24. ワークフローの話

  25. といっても大したことはしていない • 個人開発なので大したワークフローは無い • どういう順番で作ったかの話

  26. 製作期間 • 4日(約30時間) • 土日全部と、平日の夜中

  27. 制作の流れ 1. 通信デバッグ用のビルドを作成 2. VR/AR対応前の状態で動作確認 3. ARCoreを使った実装(InstantPreview) 4. Android実機確認 5.

    VR実装 6. 結合して動作確認
  28. 実機確認はツライ • 機材トラブルで時間を取られる • ビルドが遅い • 物理的に機材を使う手間がしんどい • できるだけ実機確認を後回しにする •

    もちろん、技術検証だけは先にやっておく
  29. VRとARを同時にデバッグするのは無理 • VR側の動作確認には、Viveを装着する必要がある • AR側の動作確認には、スマホを持って移動する必要がある • 1人じゃ無理!!!!!!

  30. デバッグ用のビルドファイル • アバターがアニメーションを自動再生するだけのビルド • VR側のモック化として利用 • 通信機能だけ実装しておき、モーションデータを送信する @UTJ/UCL

  31. シンプルなプロジェクトで先に作る • AR、VRは無視して単体で作れるところまで作る • モック化等の小技を駆使してデバッグをする 送信 受信 https://twitter.com/toRisouP/status/995230604928036864

  32. ARCoreを導入して実験 • Instant Preview機能が便利 • USB接続されたスマホを使ってUnityEditor上でデバッグできる ←先程のデバッグ用ビルド https://twitter.com/toRisouP/status/995640657195581440

  33. VR側を実装 • SteamVRを導入して実装 • 詳しくは後述

  34. あとは最終確認 • VR側役をやってくれる友人を用意 • 時間を合わせて起動して動作確認する https://twitter.com/toRisouP/status/996763932328058881

  35. 「ワークフロー」のまとめ • コア部分は先に作っておくと楽 • AR実装、VR実装、それぞれで共通して動かせる部分を先に作る • AR/VRの状態をモック化できるようになってるとなお良い • ARとVRはプロジェクトを分けるべきだった •

    Switch Platformがツライ
  36. VRMの使い方

  37. VRMとは • VRアプリケーション向け人型3Dアバターフォーマット • https://dwango.github.io/vrm/

  38. VRMファイルを探すには • ニコニ立体で探すのが良い • 利用許可なライセンスのモデルを探して利用 • 今回はニコニ立体ちゃんを使用 https://3d.nicovideo.jp/works/td32797

  39. Unityで使うためには • UniVRMを導入する必要がある • githubから導入すればOK • https://github.com/dwango/UniVRM • バージョンアップが頻繁 •

    (まだ安定している感じはしない)
  40. Unity上でのVRMの取り扱い方 • 2パターンある • Prefab化する方法 • 動的にロードする方法

  41. Prefab化する方法 • vrm拡張子のファイルは自動的にロードされてPrefab化される • ビルドファイルにモデルを埋め込むならこの手法が楽 • あとからユーザがモデルを差し替えるみたいなことはできない手法

  42. 動的ロードする方法 • ランタイムロードしてモデルを生成する • 後から自由にモデルを変更できるようにするならこっち • VRMの使い方として、おそらくこの方法がメイン • 今回はこちらの方法でやる 直接ファイルパスを指定してロードする場合

  43. おすすめのロード方法 • WWWで先にロードしてからVRMImporterに渡すのがおすすめ • VRMImporterのデフォルトはなぜか同期読み込み • Android実機ではWWWじゃないとロードできないディレクトリがある UniRxを導入しているとWWWもawaitできる https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Main/Common/AvaterProvider.cs

  44. 動的ロードしたVRMはどうなるのか • コンポーネントがアタッチされたGameObjectが生成される

  45. 最初からアタッチされてるコンポーネント ←メタ情報が格納されたコンポーネント ←身体の構造の設定値が格納されたコンポーネント ←表情を制御するコンポーネント ←HMDを配置するときに使うコンポーネント ←視線制御に使うコンポーネント ←同上

  46. オリジナルの制御を加える場合は • AddComponentで自作コンポーネントを設定する • 同時に初期パラメータもこのタイミングで設定する • 初期化完了のタイミングを通知する機構を用意すると便利 指の曲げ制御コンポーネント https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Main/Common/AvaterController.cs#L46

  47. 動的ロードは結構めんどうくさい • 初期化を非同期にしていかないといけない • VRMの読み込みにまず数秒かかる • スクリプトからコンポーネントの初期化が必要になる • AddComponentしたコンポーネントを手動で初期化する必要がある •

    他のコンポーネントに依存する場合はその参照解決が必要
  48. VRMアバターの制御

  49. 今回組み込んだ機能は3つ • 表情の操作 • 指の曲げ伸ばし操作 • リップシンク

  50. 表情 • Viveコントローラのタッチパッドで表情を変更する 喜 怒 楽 哀

  51. 表情の変え方 • VRMBlendShapeProxyコンポーネントを使えばOK ←これ

  52. コントローラ操作で表情変更 • VRMBlendShapeProxy.SetValue()を使って設定する • 0 – 1の範囲で指定 タッチパッドを触った座標(2次元ベクトル)と設定された表情のベクトルとの内積をとった値を使う https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Main/Common/AvaterController.cs#L137-L140

  53. 表情変更:ポイント1 • 表情を合成する場合はSetValue()の第三引数にfalseを指定 • trueの場合はその時の値で強制上書きになる • falseを指定した場合はApply()を呼び出すと合成値が反映される このタイミング(Update()内)ではすべてfalseにしておく LateUpdate()のタイミングでApply()

  54. 表情変更:ポイント2 • Lerp(線形補間)を入れると柔らかくなる Lerpなし Lerpあり https://twitter.com/toRisouP/status/995322292346306560

  55. 指の曲げ伸ばし • VRMにデフォルトでは用意されていない • スクリプトを自分で用意する必要がある • FingerControllerコンポーネント (みゅみゅさん作のスクリプトを許可をもらって改変・配布) • これを動的にアタッチして使う

    https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Main/Common/FingerController.cs
  56. コントローラ操作で指の曲げ伸ばし • 各コントローラのトリガーキーの入力を反映 • 曲げる/伸ばす の2段階のみ https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Main/Common/AvaterController.cs#L44

  57. 手の曲げ伸ばし:ポイント • 2段階しかなくてもLerpを入れればなめらかになる https://twitter.com/toRisouP/status/995312888070860801

  58. リップシンク • 音声に合わせて口パクする機能 • 今回は Oculus Lipsync Unity を使った •

    https://developer.oculus.com/downloads/package/oculus-lipsync- unity/
  59. リップシンク設定 • 音声の解析結果をそのままBlendShapeに反映すればOK • OVRLipSyncContextコンポーネントが解析結果を保持している https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Main/Common/AvaterController.cs#L81-L93

  60. VRM まとめ • アバター制御の基本的な機能が揃っており便利 • Humanoidの制御に必要なことは最低限はできそう • 「動的ロード」はちょっと難しめ • プログラムが書けないとキビシイ

    • まだ出て間もないのでドキュメント不足気味
  61. ネットワーク同期の話

  62. ネットワーク同期する情報 • アバターの姿勢 • 頭、腰、手先、足先の座標と角度 • コントローラ入力値(表情・手の曲げ伸ばしに使用) • タッチパッドの座標とトリガーキーの状態 •

    ARカメラの座標 • VR空間内にARカメラがどこにあるかを表示するため
  63. ネットワーク同期のやり方 • PUN (Photon Unity Networking) の機能をそのまま使うだけ https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Main/Common/AvaterSynchronizer.cs#L90-L134

  64. ハマりどころ • VRMの動的ロードとPhoton Cloudの相性が悪い • Photon Cloudの同期の仕組みに乗せるにはPrefab化が必要 • VRMの動的ロードを使っているとPrefabが用意できない •

    VRMのアバターを直接同期する仕組みにすることができない
  65. 図解 VRMの動的ロードを使うと同期ができない (PhotonViewはAddComponentできないため) アバター アバター 通信

  66. 解決策 • 「同期管理オブジェクト」と「アバター」を分離して作る • アバターを独立したGameObjectとして生成する • アバターが生成されたら同期管理オブジェクトに登録する • 同期管理オブジェクトがアバターの情報を同期する

  67. 図解 同期オブジェクトを仲介させることで、 データの同期を実現する アバター アバター 通信 同期オブジェクト 同期オブジェクト 姿勢書き込み 姿勢反映

  68. アバター生成時に同期登録 アバター生成完了イベントが来たら 同期管理オブジェクトへ登録する https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Main/Common/AvaterScynchronizeDispatcher.cs#L51

  69. 同期オブジェクトの様子 • 白い箱が可視化した同期用オブジェクト

  70. コツ • 受信側で姿勢の再現時にもLerpを入れるといい感じ • 補間が入って動きがなめらかになる https://twitter.com/toRisouP/status/995579063405195264

  71. 設定ミスするとこんな感じになる • 同期の設定ミスったときのやつ https://twitter.com/toRisouP/status/995565615405387776

  72. ネットワーク同期 まとめ • Photon Cloudを使えばクライアント実装のみで完結する • VRMの動的ロードと合わせるには工夫が必要 • 同時接続数は1部屋あたり10人くらいが限界そう •

    Photon Cloudの制約(メッセージ数上限) • デモ用途なら十分 • 不特定多数への生放送に用いるには専用のインフラ構築が必要
  73. VR側の実装の話

  74. Steam VRを導入 • Asset Storeから導入する

  75. IK • 終端を指定し、そこに向かって関節を制御する機能 • Inverse Kinematics(逆運動学)

  76. IKの対象にVRコントローラを指定 • HMDやコントローラの座標をIKに使うことで、アバターが 操作できるようになる • 今回はFinal IKに同梱されているVRIKコンポーネントを利用した

  77. Final IK • Unity向けのIKアセット • VR対応

  78. 実装 VRのときはコントローラのTransformをIKのターゲットにする ARのときは同期オブジェクトをIKのターゲットにする https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Main/Common/AvaterScynchronizeDispatcher.cs#L81-L94

  79. VR実装 まとめ • vtuberを実装する方法をそのまま行うだけ • ググったら情報いっぱい出てくる • VRで「結月ゆかり」になって生放送する https://qiita.com/toRisouP/items/14fe62f89808013f9f6e

  80. AR実装の話

  81. ARCore SDKを導入 • Githubからダウンロード • https://github.com/google-ar/arcore-unity-sdk/releases/tag/v1.2.0

  82. Instant Preview • USBで繋いだスマホを使って直接デバッグできる • Unity Editorで実行ボタンを押すだけ

  83. サンプルコードをそのまま流用 • HelloAR • 平面を認識してタップした位置にドロイド君を表示するサンプル • これを流用し、タップ地点の座標を取り出せるようにした

  84. 実装 • ArViewManager https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Main/ForSmartphone/AR/ArViewManager.cs#L107-L114

  85. タップ位置を基準座標にする • アバターの親Transformの座標をタップ位置に設定 https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Main/ForSmartphone/StageController.cs#L56

  86. タップした位置にアバターを表示

  87. アバターの表示サイズの変更 • uGUIのスライダーをいじるとアバターのサイズが変わる • TransformのScaleを直接変更している • 小さくしすぎると足のIKがおかしくなる

  88. IKが壊れる理由 • IKの設定値の調整不足 • アバターのサイズが変わったらIKの設定も同時に変更する必要がある (歩幅、股の開き具合など) • 単にこの調整機能を入れ忘れていただけ…

  89. Androidビルドして実機確認 • 動かすとだいたい最初は上手くいかない

  90. 動かなかった理由 • パーミッションが足りない • マイクが不許可になってた • カメラの認可ダイアログは出たのに、マイクは出なかった • モデルデータがロードできない •

    StreamingAssetsはWWWでしかロードできない問題と衝突 • UniVRMをそのまま使うとFile.ReadAllBytesでVRMをロードしようとする
  91. Androidビルドでデバッグするときは • Android Device Monitorが使える • Android SDKについてくるログ閲覧ツール • ビルド時にDevelopment

    BuildにするとDebug.Logがここに流れる
  92. 問題発生:Windowsビルドが通らない! • ARCoreを導入するとWindowsビルドが通らない • スタンドアローンビルド向けのdllが用意されていないから

  93. 回避策 • Android向けdllを無理矢理よみこませてビルドする • かなりバッドノウハウ • やはりARとVRでプロジェクトを分けたほうが良さそう… これを追加して無理矢理よみこませる

  94. AR実装 まとめ • ARCoreのサンプルコードをそのまま使っただけ • ARCoreの自体の機能はほとんど活かせてない • VRプロジェクトとの混在は避けたほうが良さそう • ビルドは無理矢理通るようになったけど、

    今度はInstant Previewがおかしくなった
  95. その他実装のコツ

  96. その1:処理の非同期化 • アバター読み込み、ネットワーク通信などで非同期処理が多い • async/await & UniRx が大活躍

  97. UniRx • Reactive Exntensions for Unity • 非同期処理、イベント処理に強くなるライブラリ • Asset

    Storeから導入可能(無料) • MITライセンス
  98. 愚直に書くと… • Actionコールバックだらけ • コルーチンもなんとかしたい

  99. async/await + UniRx • コルーチンを使わずにWWWをawaitで待てる • VRMのロードもawaitで待てる

  100. Photonの初期化周りの処理 • PhotonRxを導入するとPUNのメソッドをTask化できる • https://github.com/TORISOUP/PhotonRx

  101. PhotonRx + Task + UniRx • ボタンが押されたらログイン→処理が終わるまでボタン無効化 https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Title/LoginPresenter.cs

  102. AsyncReactiveCommand • 説明ややこしいのでQiitaみて • 【UniRx】ReactiveCommand/AsyncReactiveCommandについて • https://qiita.com/toRisouP/items/c6fba9f01e6d15dabd79

  103. その2:設計の話 • どのモードで動いているか意識せずに作りたい • いまARなのか、VRなのかをできるだけ意識せずにコードを書きたい • オープン・クローズド原則を守りたい

  104. どういうこと? • たとえば「コントローラ入力」 • VR時:Viveコントローラの入力を使う • AR時:ネットワーク通信で送られてきた値を使う • デバッグ時:キーボードの入力を使いたい •

    これをif文で書き分けるみたいなことはしたくない • DIで乗り切ろう
  105. DI(依存性注入) • 抽象化した場所に、具象クラスを後から指定する • クラスを差し替えるだけで挙動を後から変更できるようになる

  106. Zenject • Unity向けのDIのフレームワーク • DIするならこれが便利 • Asset Storeから導入可能(無料) • MITライセンス

  107. 抽象化 • 入力イベントを発行するインタフェースを定義 • UniRxのReactiveProperty化が便利 https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Main/Common/Inputs/IInputEventProvider.cs

  108. 利用時はこのインタフェースのみを触る • 実体がどのクラスであるかは無視して書く • 使うときはインタフェースしか意識しない

  109. Installer(Zenject) • どのインタフェースにどの実装を使うかを定義する機能 • このインタフェースにはこのクラスを使う、みたいなのを書く場所 読み方 IInputEventProviderおよびIInputSetableが要求された場合は、 VrInputEventProviderを注入する(その際は同じインスタンスを使い回す)

  110. Installerをシーンごとにわけて用意する • VRモード、ARモードのシーンでそれぞれ中身を変える • VRのときはVR用InputEventProvider • ARのときはネットワーク同期用InputEventProvider VRモードのときのInstaller ARモードのときのInstaller https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/

    Scripts/Scene/Main/ForPC/ForPCInstaller.cs https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Main/ForSmartphone/ForSmartphoneInstaller.cs
  111. SceneにそのInstallerを配置する • シーンを切り替えると自動的にDIする実装が切り替わる VR用のシーンで使うInstaller

  112. 後はそのまま実行すれば終わり • 設定に応じて自動的に実装が注入される • SceneLoad時に自動的に注入されていく

  113. DIはムズカシイ • 疎結合な設計ができてないと効果がない • オープン・クローズド原則 • 依存関係逆転の原則

  114. 設計の勉強をするには • この資料を見て • Unity開発で使える設計の話+Zenjectの紹介 • https://www.slideshare.net/torisoup/unityzenject

  115. Zenjectを使う上での注意点 • DIの実行にはオブジェクトの存在をZenjectに認識させる必要 がある • 直接Instantiateしたり、AddComponentするとDIされない • あらかじめSceneに配置しておくか、Zenjectのコンテナ経由で GameObjectを作る/AddComponentを実行する必要がある

  116. Photonと相性が悪い • Photon.Instantiateで生成したオブジェクトはZenjectが 検知できない • Photon経由で作ったオブジェクトはDIが実行されない

  117. 解決策 • ZenAutoInjecterコンポーネントをアタッチする • これを対象につけておくとオブジェクト生成後にZenjectに認識される • 後追いでDIが実行されるようになる

  118. ZenAutoInjectorを使う上での注意 • DIのタイミングがいつになるかわからない • Start()の実行までにDIが実行されないことがある • DIが終わったことを検知して処理を開始する仕組みにしよう

  119. DIの実行を検知する方法 • メソッドインジェクションを使う • DIが実行されたタイミングでメソッドが実行される • その中でフラグを立てるなり、イベント飛ばすなりすればよい https://github.com/TORISOUP/AR_VR_Viewer/blob/master/Assets/VrmArPlayer/ Scripts/Scene/Main/Common/SynchronizeCamera.cs#L30-L42

  120. その他実装のコツ まとめ • 非同期処理は対処法を知っておくべし • async/await, Task, UniRxの使い方を覚えておくと良さげ • Zenjectを使ったDIが非常に便利

    • 無駄なif文/switch文を減らせる • わざわざマネージャクラスをシングルトン化する必要がなくなる • デバッグやテストがやりやすくなる
  121. さいごに

  122. 今回作ってみた感想 • VRとARとネットワーク同期といろいろ盛りすぎた • やってることに対して作るのがめっちゃしんどい • でも未来は感じる • プログラマ的には楽しかった •

    非同期処理の多用&DIの多用 • キレイにDIがハマると嬉しい
  123. 現状の問題点 • 技術デモの領域を出ない設計になってる • VR1人-AR1人、の1対1通信を想定した作りになってる • VR複数-AR複数、の多対多は現状の設計じゃ無理 • スケール性がない •

    まともにサービス化するなら通信サーバの開発、インフラ構築が必要 • 個人開発じゃ技術デモくらいが限界
  124. さいごにまとめ • VR空間をARで可視化するのは夢がある • AR/MRデバイスがもうちょっと普及してくれたらありがたい • VRMが便利でオススメ • 簡単に人型アバターを動的ロードして扱えて良さげ •

    今後の3Dコンテンツの主流フォーマットになってほしいな
  125. おわり