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

AvatarMakerを支える技術 / cluster_avatarmaker_engineering

AvatarMakerを支える技術 / cluster_avatarmaker_engineering

9e32efa81b675ecd55c166fb7b0a1890?s=128

Cluster Inc.

March 04, 2022
Tweet

More Decks by Cluster Inc.

Other Decks in Technology

Transcript

  1. クラスター株式会社 @yutopp AvatarMakerを支える技術

  2. Cluster, Inc. All Rights Reserved. 話す人 @yutopp ソフトウェアエンジニア

  3. Cluster, Inc. All Rights Reserved. 本日の内容について • clusterのAvatarMaker機能を実装した際に得られたUnity開発の知見 ◦ どのような前提条件があって

    ◦ どのような調査・試行錯誤をしたか
  4. Cluster, Inc. All Rights Reserved. 大枠の話

  5. Cluster, Inc. All Rights Reserved. AvatarMakerとは • そのままcluster内でアバターを作れる機能 ◦ Windows(Desktop/VR),

    Mac, Android, iOS, Meta Quest2で利用可 能!
  6. Cluster, Inc. All Rights Reserved. AvatarMakerの要件 1. cluster内でアバターを作成できること (VR/Desktop/Mobile) 2.

    服装・髪型・色を切り替えられること 3. 顔の造形・パーツを変更できること 4. 社内外のクリエイターの方が素体の部品をアップロードできること 社内に閉じない 制作ワークフロー どこでも動く 大体いじれる
  7. Cluster, Inc. All Rights Reserved. AvatarMaker追加以前のclusterの設計

  8. Cluster, Inc. All Rights Reserved. AvatarMaker追加以前のclusterの設計 • ユーザーの方がVRMをサーバーにアップロード • clusterアプリで利用時にVRMをダウンロードして表示

  9. Cluster, Inc. All Rights Reserved. AvatarMaker追加後の設計

  10. Cluster, Inc. All Rights Reserved. AvatarMaker追加後の設計 • [new] 社内外のクリエイターの方がglTFをサーバーにアップロード •

    [new] clusterアプリで利用時にglTFをダウンロードして組み立てて表示 • [new] clusterアプリがVRMをサーバーにアップロード
  11. Cluster, Inc. All Rights Reserved. Clusterの技術構成 • クライアント ◦ Unity

    2019.4.22f ◦ MVPパターンで大体設計されている ◦ ライブラリ ▪ Zenject ▪ UniRx/UniTask ▪ etc… • サーバー ◦ Go ◦ VRM/glTFを最適化する機構をもりもり搭載している ▪ メタバースプラットフォーム clusterのserverについて(2021応用編) ▪ OSSのglTFライブラリにPull Requestを出した件について クラスター Advent Calendar 2021 参照
  12. Cluster, Inc. All Rights Reserved. Clusterの技術構成

  13. Cluster, Inc. All Rights Reserved. Clusterの技術構成 • 機能の依存関係の設計の維持を頑張ると、建て増しする際に整理しやすい ◦ 変更しやすい状態を維持することを意識するとよさそう

  14. Cluster, Inc. All Rights Reserved. 詳細の話

  15. Cluster, Inc. All Rights Reserved. 全体実装

  16. Cluster, Inc. All Rights Reserved. 全体実装 実験用アプリとclusterを別で作った。

  17. Cluster, Inc. All Rights Reserved. 全体実装 • 最初からclusterには組み込まず、独立して開発 ◦ ライブラリと試験実装アプリとして分離

    • 途中からライブラリのみcluster本体に組み込みこんだ ◦ インターフェイスの微調整などしつつ… 社内外で使うためには、 ある程度外に出せるよう に境界を引く必要があっ た…
  18. Cluster, Inc. All Rights Reserved. 全体実装 メリット • 疎結合な設計を強制できる &

    asmdefを切りやすい • 単体アプリとして動作確認のイテレーションを高速にできる デメリット • どこまで最適化するかの塩梅が難しいがち ◦ 組み込んでわかるリソースの上限・プラットフォームごとの差異など 結構あった
  19. Cluster, Inc. All Rights Reserved. glTF 2.0 おなじみ Khronos Group開発の3Dモデルを扱うファイル形式。

    (中身は基本 json + binary blob) 「glTF is the "JPEG of 3D"」 https://www.khronos.org/gltf/ かのVRM形式はglTFの上に構築されてい る
  20. Cluster, Inc. All Rights Reserved. glTF 2.0 AvatarMakerでは、glb(binary) 形式を利用。glTFの拡張領域にclusterの拡張 を定義し、そこにアバターの部品データのメタデータを格納している。

    元データは普通にブラウザでも読み 込める (cluster上では難読化して配信)
  21. Cluster, Inc. All Rights Reserved. glTF 2.0 メリット • AssetBundleのように各プラットフォームに向けて何度もビルドする必要なし

    • 標準的な規格なので、他言語のライブラリからでも読める相互運用性の高さ ◦ プラットフォームごとのデータの最適化はバックエンド側で担保できる デメリット • glTFの拡張領域を自由にライブラリから使うのが難しい マルチプラット フォームで使うに は最高
  22. Cluster, Inc. All Rights Reserved. glTF 2.0 > デメリット •

    glTFの拡張領域を自由にライブラリから使うのが難しい 解決策 UnityでglTFを扱うライブラリを丸ごと作って解決 yutopp / VGltf using (var importer = new Importer(gltfContainer, timeSlicer)) { importer.Context.Importers.Materials.AddHook(new Hooks.Part.AvatarPartVRM0MtoonImporterHook()); importer.Context.Importers.Nodes.AddHook(new VGltf.Unity.Ext.AvatarImporter()); return await importer.ImportSceneNodes(ct); } glTFのimport/export VRMのexport で利用
  23. Cluster, Inc. All Rights Reserved. アバターの合成実装 複数のglTFパーツをダウンロードし、クライアントで1つのHumanoidモデル に合成して表示する部分。 + =

    + etc…
  24. Cluster, Inc. All Rights Reserved. アバターの合成実装 ボツ案:複数のglTFパーツは単体でもHumanoidなので、合成せずに Animatorを同じ位置に重ねて表示する。

  25. Cluster, Inc. All Rights Reserved. アバターの合成実装 ボツ案:複数のglTFパーツは単体でもHumanoidなので、合成せずに Animatorを同じ位置に重ねて表示する。 メリット •

    パーツの合成処理をVRM出力時に1度だけ行えばよい デメリット • パーツ切替時にAnimationのタイミングをすべて合わせるのが非常に面倒 だった… • 必須のComponentをすべてのパーツにつけ、同期するのも大変だった
  26. Cluster, Inc. All Rights Reserved. アバターの合成実装 ボツ案:複数のglTFパーツは単体でもHumanoidなので、合成せずに Animatorを同じ位置に重ねて表示する。 メリット •

    パーツの合成処理をVRM出力時に1度だけ行えばよい デメリット • パーツ切替時にAnimationのタイミングをすべて合わせるのが非常に面倒 だった… • 必須のComponentをすべてのパーツにつけ、同期するのも大変だった Skeletonの付け替えの実行時のコス トはそこまで高くなかった (フレー ム落ちも目立たないくらい)
  27. Cluster, Inc. All Rights Reserved. アバターの合成実装 現行:glTFパーツを切り替えるたびに実行時に1つのHumanoidに合成しなお す。

  28. Cluster, Inc. All Rights Reserved. アバターの合成実装 現行:glTFパーツを切り替えるたびに実行時に1つのHumanoidに合成しなお す。 メリット •

    いくらglTFパーツが増えても、操作するアバターとしては1つの Humanoidモデル扱いできる デメリット • なし
  29. Cluster, Inc. All Rights Reserved. Bone合成 今回のAvatarMakerのglTFパーツは、Humanoidのボーンに関しては仕様を統 一しているので、切替時にHumanDescriptionの変更はしていない。 (基本はSkinnedMeshRendererのSkeletonの付け替えのみ) !Tips

    • Humanoid関連のボーンを組み直す場合は、以下の値を編集したAvatarを animatorにセットする必要がある。 ◦ HumanDescription.human ◦ HumanDescription.skeleton • Avatar.isHumanがfalseを返さないように気をつける。
  30. Cluster, Inc. All Rights Reserved. Texture合成シェーダ テクスチャや色を合成して上書きする部分。 = + 色

    + etc…
  31. Cluster, Inc. All Rights Reserved. Texture合成シェーダ マテリアルごとに、複数のテクスチャを一枚にベイクする。previewの表示と VRM出力で同じデータを使えるように、リアルタイムで合成する。 = +

    色 + etc…
  32. Cluster, Inc. All Rights Reserved. Texture合成シェーダ ボツ案 : CustomRenderTexture 「カスタムレンダーテクスチャはレンダーテクスチャの拡張機能で、これを使

    うと簡単にシェーダー付きのテクスチャを作成できます。」 https://docs.unity3d.com/ja/2019.4/Manual/class-CustomRenderTexture.html 合成 Shader Material Custom Render Texture 色々なテ クスチャ 色々なプ ロパティ
  33. Cluster, Inc. All Rights Reserved. Texture合成シェーダ ボツ案 : CustomRenderTexture メリット

    • 今どき デメリット • Android端末で異常な結果を返し続ける (真っ黒なtexture)
  34. Cluster, Inc. All Rights Reserved. Texture合成シェーダ Custom Render Texture appears

    black on mobile - Unity Answers 「fairly inane workaround…」
  35. Cluster, Inc. All Rights Reserved. Texture合成シェーダ 現行 : 1x1のメッシュに通常のShaderで描画したものを平行投影で撮影した RenderTextureを使う

    合成 Shader Material Render Texture 色々なテ クスチャ 色々なプ ロパティ 撮影ス クリプト ExecuteCommandBu fferで描画する
  36. Cluster, Inc. All Rights Reserved. Texture合成シェーダ 現行 : 1x1のメッシュに通常のShaderで描画したものを平行投影で撮影した RenderTextureを使う

    メリット • どの環境でも安定して動く、とてつもない安心感 デメリット • 枯れた技術感
  37. Cluster, Inc. All Rights Reserved. IL2CPP モバイルのときに影響を受けがちな印象ですが、普通にWindowsでバックエ ンドをIL2CPPビルドにしても再現できるものが多かった。

  38. Cluster, Inc. All Rights Reserved. IL2CPP • checkedの範囲が変わる ◦ checkedでsignedもunsignedに変換されてしまった

    https://github.com/yutopp/VJson/commit/3d2f4dbefbacf050dcad71e6f8286fa834da1261 + if ( i < 0 ) + { + throw new OverflowException(); + } o = checked((byte)i);
  39. Cluster, Inc. All Rights Reserved. IL2CPP • Type/TypeInfoのGetCustomAttributesで返ってくるインスタンスが キャッシュされてる ◦

    実装依存っぽさ… https://github.com/yutopp/VJson/commit/120020a1c90dd1f0275d0f9353eef4e089943b0a TypeHelper.GetCustomAttribute<JsonSchemaAttribute>(ty)? .MemberwiseClone();
  40. Cluster, Inc. All Rights Reserved. IL2CPP • code strippingによって静かに実行時エラーが発生 ◦

    “[Preserve]” 属性をつけて解決… https://github.com/yutopp/VJson/blob/4db11d1a89fcaa61c8d4f26cf7d2c1f9c2794f18/Packages/net.yutopp.vjs on/Runtime/Attribute.cs#L20 public class PreserveAttribute : System.Attribute { }
  41. Cluster, Inc. All Rights Reserved. IL2CPP • code strippingによって静かに実行時エラーが発生 ◦

    “[Preserve]” 属性をつけて解決… https://github.com/yutopp/VJson/blob/4db11d1a89fcaa61c8d4f26cf7d2c1f9c2794f18/Packages/net.yutopp.vjs on/Runtime/Attribute.cs#L20 • 自前定義…? • Unityに “UnityEngine.Scripting.PreserveAttribute” ない? ◦ PureC#のコード部分なので、UnityEngineへの参照を持ちたくない…
  42. Cluster, Inc. All Rights Reserved. IL2CPP • code strippingによって静かに実行時エラーが発生 ◦

    “[Preserve]” 属性をつけて解決… https://github.com/yutopp/VJson/blob/4db11d1a89fcaa61c8d4f26cf7d2c1f9c2794f18/Packages/net.yutopp.vjs on/Runtime/Attribute.cs#L20 • 自前定義…? • Unityに “UnityEngine.Scripting.PreserveAttribute” ない? ◦ PureC#のコード部分なので、UnityEngineへの参照を持ちたくない 「For 3rd party libraries that do not want to take on a dependency on UnityEngine.dll, it is also possible to define their own PreserveAttribute. The code stripper will respect that too, and it will consider any attribute with the exact name "PreserveAttribute" as a reason not to strip the thing it is applied on, regardless of the namespace or assembly of the attribute.」 https://docs.unity3d.com/2019.4/Documentation/ScriptReference/Scripting.PreserveAttribute.html
  43. Cluster, Inc. All Rights Reserved. IL2CPP • code strippingによって静かに実行時エラーが発生 ◦

    “[Preserve]” 属性をつけて解決… https://github.com/yutopp/VJson/blob/4db11d1a89fcaa61c8d4f26cf7d2c1f9c2794f18/Packages/net.yutopp.vjs on/Runtime/Attribute.cs#L20 • 自前定義…? • Unityに “UnityEngine.Scripting.PreserveAttribute” ない? ◦ PureC#のコード部分なので、UnityEngineへの参照を持ちたくない 「For 3rd party libraries that do not want to take on a dependency on UnityEngine.dll, it is also possible to define their own PreserveAttribute. The code stripper will respect that too, and it will consider any attribute with the exact name "PreserveAttribute" as a reason not to strip the thing it is applied on, regardless of the namespace or assembly of the attribute.」 https://docs.unity3d.com/2019.4/Documentation/ScriptReference/Scripting.PreserveAttribute.html “PreserveAttribute” という名前であ れば、どこに定義していても最適化を抑 制できるattributeとして扱われる (あ りがたいけれどなんだそれは…)
  44. Cluster, Inc. All Rights Reserved. IL2CPP • 開発終盤は (Windows, MacOS,

    iOS, Android, Linux) x IL2CPPビルドで 動作確認するような用心深さに… ◦ CIで回したい
  45. Cluster, Inc. All Rights Reserved. まとめ • 設計を維持するのは最終的に速い • 頑張って共通の規格を使っておくといろいろ相乗りできて便利

    • 開発イテレーションを早く回して罠をたくさん踏み抜くのが大事 ◦ インターフェースの切り方 ◦ Texture、IL2CPPのトラブルシュートなど