VRM対応のiOSアプリを開発した際に得た知見
はじめに
先日、VRM対応のiOSアプリをリリースしました。
VRMアバターをARで表示して好きな角度から眺めたり、写真を撮ったりできます。
この記事では私がアプリ開発で得た知見や躓いたところを共有できればと思います。
※VRMとは直接関係のないところもあります
「VConnect」
https://itunes.apple.com/us/app/v-connect/id1450810229
VRMについて
どんなアプリか
↓をご覧ください。
https://www.youtube.com/watch?v=WhaJ6UYb8pQ
環境
Unity
ARKit2.0
UniVRM
今回の開発ではUnityを選択しました。
理由としてはUnityの勉強がしたかったのと、UniVRMを使う必要があったからです。
ですが今はネイティブでVRMを扱えるものが出ており、CocoaPodsなどで導入できるようです。
ぶつかった問題たち
↓↓↓
デフォルトでVRMファイルを1つ入れたい
iOSアプリのディレクトリの中には Documents/
というディレクトリがあり、
この中にあるVRMファイルを読み込んでアプリ上で表示しています。
「VConnect」ではデフォルトで1つのVRMアバターが入っています。
そうしないとアプリをインストールした段階ではなんのアバターもいなくて遊べなくなってしまうので。
最初の問題はどうしたらアプリインストール時にDocuments/
の中にVRMファイルを入れられるかという事でした。
結論からいうとUnityのStreamingAssets
を使う事で解決しました。
Unity プロジェクトにおける StreamingAssets と呼ばれるフォルダーに配置したファイルはビルド先のプラットフォームの、特定のフォルダーにそのまま何も変換されない状態で保持されます。
Assets/StreamingAssets/
の中にVRMファイルを1つ配置し、それをスクリプトで処理しています。
また、Application.persistentDataPath
でDocuments/
までのパスを取得できます。
// StreamingAssets内のhogehoge.vrmを取得
var file = Application.streamingAssetsPath + "/" + "hogehoge.vrm";
// バイト配列を読み込む
byte[] byte = File.ReadAllBytes(file);
// Documents/にhogehoge.vrmという名前でbyteを保存
File.WriteAllBytes(Application.persistentDataPath + "/hogehoge.vrm", byte);
これでAssets/StreamingAssets/
の中にあるファイルをDocuments/
に保存できます。
VRMファイルのランタイムロード
ランタイムロードの方法は他の記事でもたくさん書かれていますが改めて書きます。
/Documents
からVRMファイルを取得する
// Documentsディレクトリへのパスを取得
DirectoryInfo localDir = new DirectoryInfo(Application.persistentDataPath);
// GetFilesで拡張子がvrmのファイルを全て取得して配列に入れる
FileInfo[] files = localDir.GetFiles("*.vrm");
メタ情報を取得する
// VRMファイルをbyte配列に入れる
byte[] bytes = File.ReadAllBytes("hogehoge.vrm");
VRMImporterContext context = new VRMImporterContext();
context.ParseGlb(bytes);
// ReadMetaでメタオブジェクトができる
// true, falseでサムネイルの有無を選べます
VRMMetaObject meta = context.ReadMeta(true);
// 名前
Debug.Log(meta.name);
// サムネイル
Debug.Log(meta.Thumbnail);
VRMアバターを表示する
context.ParseGlb(bytes);
context.Load();
context.ShowMeshes();
メモリリーク問題
やりたい事
AR空間にアバターを配置した後に別のキャラクターに切り替えたい。
その時に前のアバターは画面上から削除し、新しいアバターを画面に表示する。
ここでは普通にDestroy
メソッドを使えばいいと思っていました。
しかしそれではダメなのです。
なぜか
なぜDestroy
ではダメなのかというと、アバターのTextureが残ってしまいメモリリークを起こしてしまうからです。
例えばiPhone8ではメモリ使用量が1400MBを越えるとアプリがクラッシュします。
1体のアバターを表示するのに300MBくらい使います。
その内、Textureで200MBくらいあります。
なのでGameObjectをDestroyで削除してもTextureが残っているので3~4体くらいアバターを読み込むとすぐにアプリがクラッシュしてしまいます。
解決方法
Resources.UnloadUnusedAssets
を使います。
使用していないアセットをアンロードします
ヒエラルキーにあるゲームオブジェクト(スクリプトコンポーネントを含む)群で総なめして、アセットが使用されていないかを判断します。
GameObjectをDestroyするところでResources.UnloadUnusedAssets
を使う事でアセットを解放してくれました。
番外編
ARアプリをAppleに申請する際に気をつける事
ガイドラインに沿った実装をする
「VConnect」もリリースまでに数回リジェクトされていますが、ARKitのガイドラインに沿った実装ができていなかったのが原因かと思います。
どのような対応をしたかいくつか紹介します。
Anticipate that people will use your app in environments that aren’t optimal for AR.
ARが使えない状況を想定するという事ですね。
VConnectではARが使えない状況を考えてカメラを使用しない通常鑑賞モードをつけました。
https://www.youtube.com/watch?v=92HXHFBrtAU
If your app encourages user motion, introduce it gradually
「ユーザーの動きを促す場合には徐々に紹介する」
ARのアプリではカメラを床や壁に向けて平面を検出するのですが、アプリを最初に開いたユーザーにこの動作を促す場合、徐々に紹介してくれという事です。
こちらの動画を見ていただくとわかる通り、VConnectでは2つの動作を別々に促しています。
1, 平面にカメラを向ける
2, 検出した平面をタップする
https://www.youtube.com/watch?v=WhaJ6UYb8pQ
まとめ
Unityに慣れていなかったのが躓いた原因としては大きいですね。
しかし個人でモバイルアプリをリリースしたのは初めてだったので嬉しいです^^
C#も言語として好きになりました。
参考文献
https://docs.unity3d.com/ja/2018.1/Manual/StreamingAssets.html
https://docs.unity3d.com/ja/2018.1/ScriptReference/Resources.UnloadUnusedAssets.html
https://developer.apple.com/design/human-interface-guidelines/ios/system-capabilities/augmented-reality/
Author And Source
この問題について(VRM対応のiOSアプリを開発した際に得た知見), 我々は、より多くの情報をここで見つけました https://qiita.com/kouuuki/items/8e32f5b75ef78d72726e著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .