124
116

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UnityでVRMファイルをインポートして使うときの覚え書き

Last updated at Posted at 2018-06-10

はじめに

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を直接使う方法が楽です。

image.png

ランタイムロードする方法

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/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経由じゃないとアクセスできない
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と組み合わせるとこう書けます。最高では?

UniRx+async/await+WWW
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);

1.gif
両手全部曲げ伸ばししてる画像(Lerp入れるとなめらかになってよさそう)

とりあえずここまで

発見があれば追記します

124
116
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
124
116

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?