UnityのIKでモーション作成①

はじめに

pixivが無料で提供しているVRoid Studioで3Dモデルが簡単に作れるようになったので
次は動きもつくってみようとUnityでこんなのを作りました。
f:id:kanabun500kanabun:20190121204345p:plain
unityroom.com
UnityのIKを使ってモーションを作成します。
Unityroomで公開しているのはモーションは保存出来ません。


作成過程で調べたことを忘れないように残しておきます。

3Dモデル

VRoidで作成したモデルを使用しています。
UnityにインポートするにはVRM - dwango on GitHubからUniVRMをインストールしてから
3Dモデルのvrmをインポートします。

IKについて

docs.unity3d.com
IKについては公式を見てもらうとして実際にしたIKの設定は
IKで動かしたい3DモデルにAnimatorをアタッチしてAnimatorタブから
画像の右の赤〇のIKPassにチェックを入れるとIKが有効になります。
このウインドウは左の赤〇のIKの右横にある歯車を左クリックすると出てきます。
f:id:kanabun500kanabun:20190121205411p:plain

VRoid以外のモデルでIKを使う場合リグがHumanoid以外になってると使えないので
そのときはHumanoidにする必要があります。

次にスクリプトです。
IKはOnAnimatorIK関数を使います。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Animator))]
public class IKVRoid : MonoBehaviour
{
    [SerializeField]
    Transform _bodyObj = null;

    [SerializeField]
    Transform _rightHand = null;
    [SerializeField]
    Transform _rightElbow = null;

    [SerializeField, Range(0.0f, 1.0f)]
    float _rightHandWeight = 1.0f;
    [SerializeField, Range(0.0f, 1.0f)]
    float _rightElbowWeight = 1.0f;

    [SerializeField]
    Transform _lookTarget=null;

    [SerializeField, Range(0.0f, 1.0f)]
    float _lookWeight = 0.5f;
    [SerializeField, Range(0.0f, 1.0f)]
    float _bodyWeight = 0.4f;
    [SerializeField, Range(0.0f, 1.0f)]
    float _headWeight = 0.4f;
    [SerializeField, Range(0.0f, 1.0f)]
    float _eyeWeight = 0.4f;

    Animator _animator;

    void Start()
    {
        _animator = GetComponent<Animator>();
    }

    void OnAnimatorIK()
    {
        if (_bodyObj != null)
        {
            _animator.bodyPosition = _bodyObj.position;
            _animator.bodyRotation = _bodyObj.rotation;
        }

        if (_rightHand != null)
        {
            _animator.SetIKPositionWeight(AvatarIKGoal.RightHand, _rightHandWeight);
            _animator.SetIKRotationWeight(AvatarIKGoal.RightHand, _rightHandWeight);
            _animator.SetIKPosition(AvatarIKGoal.RightHand, _rightHand.position);
            _animator.SetIKRotation(AvatarIKGoal.RightHand, _rightHand.rotation);
        }

        if (_rightElbow != null)
        {
            _animator.SetIKHintPositionWeight(AvatarIKHint.RightElbow, _rightElbowWeight);
            _animator.SetIKHintPosition(AvatarIKHint.RightElbow, _rightElbow.position);

        }

        if (_lookTarget != null)
        {
            _animator.SetLookAtWeight(_lookWeight, _bodyWeight, _headWeight, _eyeWeight);
            _animator.SetLookAtPosition(_lookTarget.position);
        }
    }
}

左手、右足、左足は省略してます。
SetIKはAvatarIKGoal.名前で右手や左足を指定します。
SetIKHintはAvatarIKHint.名前で右肘や左膝を指定します。
このスクリプトを3Dモデルにアタッチしてモデルとは別にIKの位置を決めるオブジェクトを登録します。
アニメーション中IKを有効にしてオブジェクトを動かすと対応した位置にモデルが動くようになります。


ここでは使ってませんが

_animator.SetBoneLocalRotation(HumanBodyBones.RightHand,Quaternion rotation);

を使えばHumanBodyBones.名前でボーンを指定してボーンの角度を決められます。


続きます。