見出し画像

VRM入門

1. VRMとは

「VRM」は、プラットフォーム非依存の3Dアバターファイルフォーマットです。「人型のキャラクター・アバター」において、細かいモデルデータの差違を吸収し、アプリケーション側での取り扱いしやすくすることを目的としています。UnityでVRMファイルを読み書きする標準実装が提供されますが、フォーマット自体はプラットフォーム非依存であり他エンジンや環境でも取り扱うことが可能です。

2. VRMの特徴

VRMの特徴は次のとおりです。

・プラットフォーム非依存で人型のキャラクター3Dモデルデータを取り扱うことが可能。
・3D標準の「glTF2.0」をベースに、人型モデルを取り扱うための制約と拡張を加えたフォーマット。
・テクスチャやマテリアルなどすべてのデータを含めて1ファイルにまとめられる。
・スケール(1.00 = 1m)・座標系と向き(Y-up, -Z方向向き)など標準仕様が決まっている。
・キャラクターの表情を共通APIで操作できる。
・VRでのアバター利用のための、「一人称視点再現のための情報」に対応。
・キャラクターの髪の毛などについて、物理エンジンに依存しない「揺れ物」標準実装を用意。
・標準実装としてのマテリアル(シェーダ)を用意。
・タイトル・作者名などのメタ情報だけでなく、サムネイルやライセンス情報も内包可能。

3. UniVRMのインストール

「UniVRM」は、UnityでVRMファイルを読み書きする標準実装です。

(1)UniVRMのリリースページから最新のunitypackageファイル(UniVRM-0.53.0_6b07.unitypackage)をダウンロード
(2)Unityのメニュー「Assets → Import Package → Custom Package」 で先ほどダウンロードしたunitypackageファイルを選択。
(3)Importボタンを押してインポート。

4. VRMモデルの入手

今回は、「ニコニ立体ちゃん (VRM)」を使います。
以下のサイトからダウンロードしてください。vrmファイルがモデルファイルになります。

ニコニ立体ちゃん (VRM)

5. VRMモデルの利用

UnityでVRMモデルを使う方法は、2パターンあります。

・Prefabとして静的に配置
・C#スクリプトで動的に配置

◎Prefabとして静的に配置
vrmファイルを、「Assets」にドラッグ&ドロップすると、自動的にPrefabが生成されます。生成されたPrefabをHierarchyにドラッグ&ドロップすると、シーンに表示されます。

画像1

◎C#スクリプトで動的に配置
「Assets/StreamingAssets」にvrmファイルを配置します。そして、Hierarchyに空のGameObjectを生成し、以下のスクリプトを追加します。

【VRMLoader.cs】

using UnityEngine;
using VRM;

//VRMローダー
public class VRMLoader : MonoBehaviour {
    //スタート時に呼ばれる
    void Start() {
        var path = Application.streamingAssetsPath + "/" + "AliciaSolid.vrm";

        //コンテキストの生成
        var context = new VRMImporterContext();
        context.Parse(path);

        //モデルの読み込み
        context.LoadAsync(() => {
            //位置の指定
            var gameObject = context.Root;
            gameObject.transform.position = new Vector3(0, 0, 0);

            //メッシュの表示
            context.ShowMeshes();
        });
    }
}

6. アニメーションの追加

VRMモデルにアニメーションを追加するには、VRMモデルの「Animator - Controller」に「AnimatorController」を追加します。
今回は、「ユニティちゃん3Dモデルデータ」に付属する「AnimatorController」を利用します。以下のサイトから「ユニティちゃん3Dモデルデータ」をunitypackageファイルをダウンロードしてください。

ユニティちゃん3Dモデルデータ

画像5

「UniVRM」と同様の方法でインストールします。

「/Assets/UnityChan/Animators」に「AnimatorController」が存在するので、「UnityChanActionCheck」を、Hierarchyに追加したVRMモデルの「Animator - Controller」に追加します。

実行すると、アニメーションします。

画像2

7. 表情の変更

実行中に、「VRM Blend Shape Proxy」で表情のパラメータを変更することができます。右目をつむりながら、「お」の口にするなどができます。

画像3

表情パラメータの種類は、次のとおり。

・NEUTRAL: ニュートラル
・A: 「あ」の口
・I: 「い」の口
・U: 「う」の口
・E: 「え」の口
・O: 「お」の口
・BLINK: 目をつむる
・JOY: 喜
・ANGRY: 怒
・SORROW: 哀
・FUN: 楽
・LOOKUP: 上向く
・LOOKDOWN: 下向く
・LOOKLEFT: 左向く
・LOOKRIGHT: 右向く
・BLINK_L: 左目をつむる
・BLINK_R: 右目をつむる

8. いろいろなアニメーションの表示

「AnimatorController」には、複数のアニメーション(状態)が含まれています。「Add Component」で「Idle Changer」を追加することで、状態を切り替えるUIが追加され、様々なアニメーションが見れるようになります。

画像4

9. 瞬きの追加

目の瞬きを追加するには、「Add Component」で「Blinker」を追加します。

10. ソースコードからアニメーションを切り替え

ソースコードからのアニメーションの切り替え例は次のとおりです。

【AnimatorTest.cs】

using UnityEngine;

//Animatorのテストコード
public class AnimatorTest : MonoBehaviour {
    private Animator anim;
    private AnimatorStateInfo currentState;

    //スタート時に呼ばれる
    void Start() {
        anim = GetComponent<Animator>();
        currentState = anim.GetCurrentAnimatorStateInfo(0);
    }

    //更新時に呼ばれる
    void Update() {
        //次へ
        if (Input.GetKeyDown("up")) {
            anim.SetBool("Next", true);
        }

        //前へ
        if (Input.GetKeyDown("down")) {
            anim.SetBool("Back", true);
        }

        //状態遷移時に初期化
        AnimatorStateInfo state = anim.GetCurrentAnimatorStateInfo(0);
        if (currentState.nameHash != state.nameHash) {
            currentState = state;
            anim.SetBool("Next", false);
            anim.SetBool("Back", false);
        }
    }
}

11. ソースコードから表情を切り替え

ソースコードからの表情の切り替え例は次のとおりです。

【BlendShapeTest.cs】

using UnityEngine;
using VRM;

//BlendShapeのテスト
public class BlendShapeTest : MonoBehaviour {
    private VRMBlendShapeProxy proxy;

    //スタート時に呼ばれる
    void Start() {
    }

    //更新時に呼ばれる
    void Update() {
        //VRMBlendShapeProxyはUpdate開始後でないと取得できない
        if (proxy == null) {
            proxy = GetComponent<VRMBlendShapeProxy>();
        } else {
            //口をあける
            if (Input.GetKeyDown("up")) {
                proxy.SetValue(BlendShapePreset.O, 1f);
            }

            //口をとじる
            if (Input.GetKeyDown("down")) {
                proxy.SetValue(BlendShapePreset.O, 0f);
            }
        }
    }
}


この記事が気に入ったらサポートをしてみませんか?