VR向けアバターフォーマット「VRM」をランライムで読み込んで、その後VRIKにアタッチさせて動かしたかったので、手順をメモ。
準備
VRM
UniVRM-0.40.unitypackageをインポートしておく
https://github.com/dwango/UniVRM/releases
VRIK
VRIKが必要なのでFinal IKをインポートしておく
Final IK - Asset Store
VRMモデル
下記のリンクからVRMモデルをダウンロードして、UnityのWWWクラスで取得できるパスに置いておく
「ニコニ立体ちゃん (VRM)」 / ニコニ立体 さんの作品 - ニコニ立体
実装
1. VRMをランタイムで読み込む
githubにあるRuntimeSampleLoader.unitypackageを参考に読み込み処理を実装
https://github.com/dwango/UniVRM/releases
2. VRIKをアタッチさせる
var vrIK = avatar.AddComponent<VRIK>();
3. VRIKのリファレンスを設定させる
vrIK.AutoDetectReferences();
4. エラーがでるので解除
今のままだと下記のエラーがでる
NullReferenceException: Object reference not set to an instance of an object RootMotion.FinalIK.IKSolverVR+Arm.Stretching () (at Assets/Plugins/RootMotion/FinalIK/IK Solvers/IKSolverVRArm.cs:220)
初期化処理を入れておく
// NullReferenceエラーがでるので初期化しておく vrIK.solver.leftArm.stretchCurve = new AnimationCurve (); vrIK.solver.rightArm.stretchCurve = new AnimationCurve ();
5. 頭、左手、右手のターゲットを指定
vrIK.solver.spine.headTarget = headTarget.transform; vrIK.solver.leftArm.target = leftHandTarget.transform; vrIK.solver.rightArm.target = rightHandTarget.transform;
6. その他微調整(任意)
// 歩幅の設定 vrIK.solver.locomotion.footDistance = 0.1f;
最終的なスクリプト
VRMRuntimeLoader.cs
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using VRM; using RootMotion.FinalIK; namespace ViRD.Samples{ public class VRMRuntimeLoader : MonoBehaviour { void Start() { // 読み込むURLを指定 var path = "http://hogehoge/AliciaSolid.vrm"; StartCoroutine(LoadVrmCoroutine(path, go => { // ターゲットを仮作成 var headTarget = new GameObject(); var leftHandTarget = new GameObject(); var rightHandTarget = new GameObject(); headTarget.transform.position = new Vector3(0f, 1.5f, 0f); leftHandTarget.transform.position = new Vector3(-0.5f, 0.8f, 0f); rightHandTarget.transform.position = new Vector3(0.5f, 0.8f, 0f); // VRIKのセットアップ SetupVRIK(go, headTarget, leftHandTarget, rightHandTarget); })); } IEnumerator LoadVrmCoroutine(string path, Action<GameObject> onLoaded) { var www = new WWW(path); yield return www; if(!string.IsNullOrEmpty(www.error)) { Debug.LogError(www.error); yield break; } VRMImporter.LoadVrmAsync(www.bytes, onLoaded); } void SetupVRIK(GameObject avatar, GameObject headTarget, GameObject leftHandTarget, GameObject rightHandTarget){ // VRIKを設定 var vrIK = avatar.AddComponent<VRIK>(); // リファレンス紐付け vrIK.AutoDetectReferences(); // NullReferenceエラーがでるので初期化しておく vrIK.solver.leftArm.stretchCurve = new AnimationCurve (); vrIK.solver.rightArm.stretchCurve = new AnimationCurve (); // 頭や腕のターゲット設定 vrIK.solver.spine.headTarget = headTarget.transform; vrIK.solver.leftArm.target = leftHandTarget.transform; vrIK.solver.rightArm.target = rightHandTarget.transform; // 歩幅の設定 vrIK.solver.locomotion.footDistance = 0.1f; } } }