はじめに
2018年4月に、ドワンゴが「VRM」という新しい3Dアバターフォーマットを公開しました。
今回はこのVRMをUnity上で利用する方法についてのメモ書きです。
(随時追加します。)
なお、この記事は「VRMファイルをUnity上でどう扱うか」についての記事です。
3DモデルをVRMファイルに変換する話はしません。
一緒にみると良いかもしれない資料
以前作った、VRのアバターをARで操作するシステム(twitter)について解説した資料です。
この資料でも触れているVRMについての情報をこの記事は含んでいます。
使い方メモ
0.UniVRMの各種使い方など
まずは公式ドキュメントを読みましょう。
下の方にBlendShape(表情変更)のやり方についての説明とかあります。
1. UniVRMの導入
UnityでVRMを利用する場合はUniVRMを用いることになるでしょう。
公式でサポートされているVRMインポータ/エクスポータです。
導入方法は簡単で、releaseページから最新のunitypackageをダウンロードして導入すればOKです。
なお、2018年6月時点ではUniVRMは週に1~2回の頻度でアップデートが実行されています。
アップデートのたびに微妙に仕様が変更されたり、バグって壊れたりすることがあるので小まめにバージョンを確認することを推奨します。
2. VRMモデルのインポート方法
VRMファイルをUnityで利用する方法は2パターンあります。
- Prefab化する
- ランタイムロードする
Prefab化する方法
VRMファイルをUnityの/Assets
以下に配置した場合、自動的にUniVRMがインポートしてPrefabに変換してくれます。
ビルドにVRMモデルを埋め込んでしまう場合はこのPrefabを直接使う方法が楽です。
ランタイムロードする方法
VRMをスクリプトからランタイムロードすることで、動的にVRMモデルをGameObjectとしてシーン上に出現させることができます。
ランタイムロードする場合は、VRMファイルをStreamingAssets
などに配置するとよいでしょう。
void Start()
{
var path = Application.streamingAssetsPath + "/" + "AliciaSolid.vrm";
// Actionコールバックで生成されたGameObjectが返される
VRMImporter.LoadVrmAsync(path, gameObject =>
{
gameObject.transform.position = new Vector3(1, 1, 1);
});
}
なお、UniVRMがv0.37
以降であればasync/await
を用いてロード待ちをすることができます。
async void Start()
{
var path = Application.streamingAssetsPath + "/" + "AliciaSolid.vrm";
// awaitでロード待機
var gameObject = await VRMImporter.LoadVrmAsync(path);
gameObject.transform.position = new Vector3(1, 1, 1);
}
おすすめのロード方法
WWW
を使って先にbyte[]
ファイルを読み込んでしまい、それをVRMImporter.LoadVrmAsync
に渡す方法を推奨します。
理由は次の2点です。
-
VRMImporter.LoadVrmAsync
が内部でFile.ReadAllBytes
を使用しており、これが同期読み込みのため重い(v0.38時点) -
StreamingAssets
以下のファイルはAndroid実機の場合はWWW
経由じゃないとアクセスできない
IEnumerator LoadVrmCoroutine(string path, Action<GameObject> onLoaded)
{
var www = new WWW(path);
yield return www;
VRMImporter.LoadVrmAsync(www.bytes, onLoaded);
}
void Start()
{
var path = Application.streamingAssetsPath + "/" + "AliciaSolid.vrm";
StartCoroutine(LoadVrmCoroutine(path, go =>
{
go.transform.position = new Vector3(1, 1, 1);
}));
}
ちなみに、UniRx
を導入してasync/await
と組み合わせるとこう書けます。最高では?
async void Start()
{
var path = Application.streamingAssetsPath + "/" + "AliciaSolid.vrm";
var www = new WWW(path);
await www;
var go = await VRMImporter.LoadVrmAsync(www.bytes);
go.transform.position = new Vector3(1, 1, 1);
}
3.指の曲げ伸ばし
いろいろ手法があると思うけど、自分はこのスクリプトをAddComponent
して使っています。
// 対象アバターのGameObjectのrootにアタッチ
var fingerController = gameObject.AddComponent<FingerController>();
// 左手全部曲げる
fingerController.FingerRotation(FingerController.FingerType.LeftAll, 1.0f);
// 右手の人差し指だけ伸ばしてあと全部曲げる
fingerController.FingerRotation(FingerController.FingerType.RightAll, 1.0f);
fingerController.FingerRotation(FingerController.FingerType.RightIndex, 0.0f);
両手全部曲げ伸ばししてる画像(Lerp入れるとなめらかになってよさそう)
とりあえずここまで
発見があれば追記します