【Unity】アニメーションクリップ(人型)をスクリプトで作成する

今回は人型キャラのアニメーションクリップをスクリプトで作成する方法を紹介したいと思います。

使い方としてはゲーム上で動くキャラを録画するのではなくモーションとしてアニメーションクリップにしたいだったり、モーションキャプチャーをゲーム上で行いそのデータでアニメーションクリップを作成したいなどを想定しています。

 

まず作成するにあたりクリップに必要な情報はなにか知る必要があります。

その情報とは

どのオブジェクトどの時間にどんななのか

ということです。

たとえば1秒の手の動かすアニメーションでは

(オブジェクト)のlocalPosition.x(何)が0秒(時間)に(値)

(オブジェクト)のlocalPosition.x(何)が1秒(時間)に(値)

という情報があればlocalPosition.xをうごかすアニメーションに必要な情報は取得完了ということになります。ここではlocalPosition.xだけで例を出しましたが、他の値も動かしたいのであれば他の値もそれぞれ取得します。

 

上記の情報を格納するものを

AnimationCurve(アニメーションカーブ)といいます。

そしてこのアニメーションカーブのなかのどの時間にどんなの部分を

keyframe(キーフレーム)といいます。

 

これをUnity上で見ると

f:id:graphicalpoxy:20190615152525p:plain

こんなかんじで

赤枠AnimationCurve(アニメーションカーブ)

青枠keyframe(キーフレーム)になります。

アニメーションカーブにキーフレームをどんどん足していくと一つの要素のアニメーションが完成します。

公式では

AnimationCurve 時間の経過をとおして評価される Keyframes の集合を保存します。 

keyframe アニメーションカーブでの単一のキーフレームです。

図があるとなるほどとなりますよね。

ということで知識が充実してきたところでスクリプトの例を出して終わりたいと思います。

詳しい情報はスクリプトに書きますね。

 

 

 

スクリプト作成

 

今回のスクリプトでは適当な値で1秒のアニメーションを作っています。

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

public class animetest : MonoBehaviour
{
    private AnimationClip _clip;
    private Animator _animator;

    [SerializeField]
    private Transform _unitychan;
    private Transform _leftHand;

    private string _path;
    private AnimationCurve handPosXCurve;
    private AnimationCurve handPosYCurve;
    private List<Keyframe> keyframesPosX;
    private List<Keyframe> keyframesPosY;

    void Start()
    {
        _animator = _unitychan.GetComponent<Animator>();
        _leftHand = _animator.GetBoneTransform(HumanBodyBones.LeftHand);
        _path = FindPath();
        handPosXCurve = new AnimationCurve();
        handPosYCurve = new AnimationCurve();

        SetKeyframes();
        AddKeyframe();
        FindPath();
        SetAnimationCurve();
        ClipSave();
    }

    // keyframeの作成.
    // keyframe(float time, float value)
    // 値は適当です
    private void SetKeyframes()
    {
        keyframesPosX.Add(new Keyframe(0, 0));
        keyframesPosX.Add(new Keyframe(1, 1));
        keyframesPosY.Add(new Keyframe(0, 2));
        keyframesPosY.Add(new Keyframe(1, 3));
    }

    // CurveにKeyframeを追加.
    private void AddKeyframe()
    {
        for (var i = 0; i < keyframesPosX.Count; i++)
        {
            handPosXCurve.AddKey(keyframesPosX[i]);
        }
        for (var i = 0; i < keyframesPosY.Count; i++)
        {
            handPosYCurve.AddKey(keyframesPosY[i]);
        }
    }

    // 適応するオブジェクトのパス検索.
    private string FindPath()
    {
        string objectPath = _leftHand.name;

        Transform parent = _leftHand.parent;

        while (parent != null)
        {
            objectPath = parent.name + "/" + objectPath;
            parent = parent.parent;
        }

        return objectPath;
    }

    // アニメーションクリップの作成.
    // SetCurve(動かしたいオブジェクトパス,タイプ,プロパティ,AnimationCurve)
    private void SetAnimationCurve()
    {
        _clip.SetCurve(_path, typeof(Transform), "localPosition.x", handPosXCurve);
        _clip.SetCurve(_path, typeof(Transform), "localPosition.y", handPosYCurve);
    }

    // 保存(UnityEditorのみの動作).
    private void ClipSave()
    {
        AssetDatabase.CreateAsset(_clip, "Assets/CreateAnime");
        AssetDatabase.Refresh();
    }
}

 

間違っていたらすいません。たぶんなんかわすれたけど最後にないかつけないと滑らかに動かないような気が・・・

一応確認のためにクリップをほぞんできるようにしています。エディター上でだけですけどね。

 

今回は左手を動かすというパターンを作りましたが、これを基盤につくれば全身でできます。またキーフレームも最低限しか用意していませんがたくさんつくるといい感じになります。

モーションキャプチャー中にキーフレームを作成しまくって、これでくりっぷを作成するとすばらしいアニメーションが出来ることでしょう。