simplestarの技術ブログ

目的を書いて、思想と試行、結果と考察、そして具体的な手段を記録します。

Unity:VRMのランタイムロードがなんもわからん

こちら「2019年なんもわからんカレンダー」1月3日の記事です。

前回の記事は
Kazushige Mori(Cz_mirror) (@Cz_mirror) | Twitter さんによる「SmartRig Bipedなんもわからん。。」でした。

cz-mirror.hatenablog.com

前書き

自分だけの3Dキャラクターをあらゆるゲームに登場させるという、全人類の悲願(笑)がまさに今日成就しようとしています。
ウソだと思うあなた、次の VRoid Hub のサイトの文句をちょっと調べてみてください。

>いま、あなたのキャラクターが動き出す。
hub.vroid.com

  • 自慢の3Dキャラを3分でおひろめ。
  • 登録したキャラで遊べちゃう。
  • お気に入りがなければ、自分ですぐに作れます。

ということで VRoid Hub で公開されている VRM (3Dキャラクターデータフォーマット)をゲーム実行後にダウンロードして読み込ませる方法を確かめたいと思いまして
なんもわからん状態から調べて完全に理解した状態まで来たので、実装詳細を記録しておきます。

VRM を Unity ゲームで読み込むには?

VRM - dwango on GitHub 公式ドキュメントにざっと目を通し、次の UniVRM を使うと良いことが確認できました。
github.com

そんな UniVRM を使って VRM をランタイムロードするには?と調べるとドンピシャな記事を見つけました。
qiita.com

こちらの記事の内容で完全に理解できてしまうのですが、本記事では Unity 初心者にもわかるように詳細に作業ログを残します。

Unity Hub から Unity を起動

簡単な操作ですが、Unity Hub は比較的新しいツールなので、Unity ベテランの方でも使ったことがない人もいます。
今回は Unity 2018.3.0f2 を使い、空のプロジェクトを作成して起動しました。

UniVRM パッケージをインポート

次の UniVRM の README に従って最新のUniVRM-0.xx.unitypackageファイルをダウンロードして、Unityにインポートします。
GitHub - dwango/UniVRM: Unity package that can import and export VRM format

Humanoid適当アニメーションデータを用意

Unity の公開アセット(無料)の中から Unity ちゃんの歩行アニメーションをダウンロードして、Unityにインポートします。
unity-chan.com

ブレンドツリーのアニメーションコントローラを作成

こちらの過去記事で紹介している WalkRun ステートを持つ AnimatorController が用意できればゴールです。
simplestar-tech.hatenablog.com

ランタイムロードのコードを記述

GameManager.cs

using System.IO;
using UnityEngine;
using VRM;

public class GameManager : MonoBehaviour
{
    [SerializeField]
    GameObject m_target;
    [SerializeField]
    RuntimeAnimatorController m_animCtrl;

    private void Start()
    {
        LoadModel("C:/Users/simpl/Downloads/Vita.vrm");
    }

    void LoadModel(string path)
    {
        if (!File.Exists(path))
        {
            Debug.LogError("file not found path = " + path);
            return;
        }

        Debug.LogFormat("{0}", path);
        var context = new VRMImporterContext();
        var file = File.ReadAllBytes(path);
        context.ParseGlb(file);
        context.Load();
        context.ShowMeshes();
        context.EnableUpdateWhenOffscreen();
        context.ShowMeshes();
        SetModel(context.Root);
    }

    void SetModel(GameObject go)
    {
        if (go != null)
        {
            var lookAt = go.GetComponent<VRMLookAtHead>();
            if (lookAt != null)
            {
                go.AddComponent<Blinker>();

                lookAt.Target = m_target.transform;
                lookAt.UpdateType = UpdateType.LateUpdate; // after HumanPoseTransfer's setPose
            }

            var animCtrl = go.GetComponent<Animator>();
            if (animCtrl && animCtrl.runtimeAnimatorController == null)
            {
                animCtrl.runtimeAnimatorController = m_animCtrl;
            }
        }
    }
}
GameManager のインスペクタを設定

上記コードを空のオブジェクトに割り当てて、先ほど「mecanimのイロハ」で作った AnimatorController をインスペクタで設定します。

f:id:simplestar_tech:20190103182659j:plain
GameManager のインスペクタビューの様子

VRoid Hub から利用OKなVRMを取得

今回は VRoid Project が提供しているヴィータ.vrmをダウンロードして手元に用意しました。
hub.vroid.com

コードで期待しているパスにリネームして配置してあげます。
今回はコード内容からダウンロードフォルダに置くのが正解でしたね。
具体的にはこちら "C:/Users/simpl/Downloads/Vita.vrm"

Play モードで動作確認

ゲームを起動すると Start 関数が初回に呼ばれるので、このときにダウンロードフォルダにある Vita.vrm を読み込みます。
読み込み終えたゲームオブジェクトに AnimatorController が割り当たるので、次の動画のように歩くアニメーションを確認することができます。

f:id:simplestar_tech:20190103184255g:plain
Vira.vrm ロード結果インスタンスにAnimatorController適用結果

まとめ

UniVRMを使ってVRMのランタイムロードを行って、そのインスタンスブレンドアニメを適用して期待通り歩行~走行するモーションを確認しました。
それを行う細かい手順を具体的に記録して公開しました。

もっと深く調べたい人へ

私の貧弱なサンプルでは不満な方も多いと思いますので dwango さんが用意しているVRMの公式 Unity サンプルをご確認ください。
github.com

次の日の記事はこちら

lilea.net