$30 off During Our Annual Pro Sale. View Details »

AvatarMakerを支える技術 / cluster_avatarmaker_engineering

AvatarMakerを支える技術 / cluster_avatarmaker_engineering

Cluster, Inc.

March 04, 2022
Tweet

More Decks by Cluster, Inc.

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

  3. Cluster, Inc. All Rights Reserved.
    本日の内容について
    ● clusterのAvatarMaker機能を実装した際に得られたUnity開発の知見
    ○ どのような前提条件があって
    ○ どのような調査・試行錯誤をしたか

    View Slide

  4. Cluster, Inc. All Rights Reserved.
    大枠の話

    View Slide

  5. Cluster, Inc. All Rights Reserved.
    AvatarMakerとは
    ● そのままcluster内でアバターを作れる機能
    ○ Windows(Desktop/VR), Mac, Android, iOS, Meta Quest2で利用可
    能!

    View Slide

  6. Cluster, Inc. All Rights Reserved.
    AvatarMakerの要件
    1. cluster内でアバターを作成できること (VR/Desktop/Mobile)
    2. 服装・髪型・色を切り替えられること
    3. 顔の造形・パーツを変更できること
    4. 社内外のクリエイターの方が素体の部品をアップロードできること
    社内に閉じない
    制作ワークフロー
    どこでも動く 大体いじれる

    View Slide

  7. Cluster, Inc. All Rights Reserved.
    AvatarMaker追加以前のclusterの設計

    View Slide

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

    View Slide

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

    View Slide

  10. Cluster, Inc. All Rights Reserved.
    AvatarMaker追加後の設計
    ● [new] 社内外のクリエイターの方がglTFをサーバーにアップロード
    ● [new] clusterアプリで利用時にglTFをダウンロードして組み立てて表示
    ● [new] clusterアプリがVRMをサーバーにアップロード

    View Slide

  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 参照

    View Slide

  12. Cluster, Inc. All Rights Reserved.
    Clusterの技術構成

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  17. Cluster, Inc. All Rights Reserved.
    全体実装
    ● 最初からclusterには組み込まず、独立して開発
    ○ ライブラリと試験実装アプリとして分離
    ● 途中からライブラリのみcluster本体に組み込みこんだ
    ○ インターフェイスの微調整などしつつ…
    社内外で使うためには、
    ある程度外に出せるよう
    に境界を引く必要があっ
    た…

    View Slide

  18. Cluster, Inc. All Rights Reserved.
    全体実装
    メリット
    ● 疎結合な設計を強制できる & asmdefを切りやすい
    ● 単体アプリとして動作確認のイテレーションを高速にできる
    デメリット
    ● どこまで最適化するかの塩梅が難しいがち
    ○ 組み込んでわかるリソースの上限・プラットフォームごとの差異など
    結構あった

    View Slide

  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の上に構築されてい

    View Slide

  20. Cluster, Inc. All Rights Reserved.
    glTF 2.0
    AvatarMakerでは、glb(binary) 形式を利用。glTFの拡張領域にclusterの拡張
    を定義し、そこにアバターの部品データのメタデータを格納している。
    元データは普通にブラウザでも読み
    込める
    (cluster上では難読化して配信)

    View Slide

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

    View Slide

  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
    で利用

    View Slide

  23. Cluster, Inc. All Rights Reserved.
    アバターの合成実装
    複数のglTFパーツをダウンロードし、クライアントで1つのHumanoidモデル
    に合成して表示する部分。
    + =
    + etc…

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  28. Cluster, Inc. All Rights Reserved.
    アバターの合成実装
    現行:glTFパーツを切り替えるたびに実行時に1つのHumanoidに合成しなお
    す。
    メリット
    ● いくらglTFパーツが増えても、操作するアバターとしては1つの
    Humanoidモデル扱いできる
    デメリット
    ● なし

    View Slide

  29. Cluster, Inc. All Rights Reserved.
    Bone合成
    今回のAvatarMakerのglTFパーツは、Humanoidのボーンに関しては仕様を統
    一しているので、切替時にHumanDescriptionの変更はしていない。
    (基本はSkinnedMeshRendererのSkeletonの付け替えのみ)
    !Tips
    ● Humanoid関連のボーンを組み直す場合は、以下の値を編集したAvatarを
    animatorにセットする必要がある。
    ○ HumanDescription.human
    ○ HumanDescription.skeleton
    ● Avatar.isHumanがfalseを返さないように気をつける。

    View Slide

  30. Cluster, Inc. All Rights Reserved.
    Texture合成シェーダ
    テクスチャや色を合成して上書きする部分。
    =
    + 色 + etc…

    View Slide

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

    View Slide

  32. Cluster, Inc. All Rights Reserved.
    Texture合成シェーダ
    ボツ案 : CustomRenderTexture
    「カスタムレンダーテクスチャはレンダーテクスチャの拡張機能で、これを使
    うと簡単にシェーダー付きのテクスチャを作成できます。」
    https://docs.unity3d.com/ja/2019.4/Manual/class-CustomRenderTexture.html
    合成
    Shader
    Material
    Custom
    Render
    Texture
    色々なテ
    クスチャ
    色々なプ
    ロパティ

    View Slide

  33. Cluster, Inc. All Rights Reserved.
    Texture合成シェーダ
    ボツ案 : CustomRenderTexture
    メリット
    ● 今どき
    デメリット
    ● Android端末で異常な結果を返し続ける (真っ黒なtexture)

    View Slide

  34. Cluster, Inc. All Rights Reserved.
    Texture合成シェーダ
    Custom Render Texture appears black on mobile - Unity Answers
    「fairly inane workaround…」

    View Slide

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

    View Slide

  36. Cluster, Inc. All Rights Reserved.
    Texture合成シェーダ
    現行 : 1x1のメッシュに通常のShaderで描画したものを平行投影で撮影した
    RenderTextureを使う
    メリット
    ● どの環境でも安定して動く、とてつもない安心感
    デメリット
    ● 枯れた技術感

    View Slide

  37. Cluster, Inc. All Rights Reserved.
    IL2CPP
    モバイルのときに影響を受けがちな印象ですが、普通にWindowsでバックエ
    ンドをIL2CPPビルドにしても再現できるものが多かった。

    View Slide

  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);

    View Slide

  39. Cluster, Inc. All Rights Reserved.
    IL2CPP
    ● Type/TypeInfoのGetCustomAttributesで返ってくるインスタンスが
    キャッシュされてる
    ○ 実装依存っぽさ…
    https://github.com/yutopp/VJson/commit/120020a1c90dd1f0275d0f9353eef4e089943b0a
    TypeHelper.GetCustomAttribute(ty)?
    .MemberwiseClone();

    View Slide

  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 { }

    View Slide

  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への参照を持ちたくない…

    View Slide

  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

    View Slide

  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として扱われる (あ
    りがたいけれどなんだそれは…)

    View Slide

  44. Cluster, Inc. All Rights Reserved.
    IL2CPP
    ● 開発終盤は (Windows, MacOS, iOS, Android, Linux) x IL2CPPビルドで
    動作確認するような用心深さに…
    ○ CIで回したい

    View Slide

  45. Cluster, Inc. All Rights Reserved.
    まとめ
    ● 設計を維持するのは最終的に速い
    ● 頑張って共通の規格を使っておくといろいろ相乗りできて便利
    ● 開発イテレーションを早く回して罠をたくさん踏み抜くのが大事
    ○ インターフェースの切り方
    ○ Texture、IL2CPPのトラブルシュートなど

    View Slide